From e20920d39b3b17c1686cbe718904498c6d6b7a51 Mon Sep 17 00:00:00 2001 From: woikos Date: Thu, 22 Jan 2026 11:04:09 +0100 Subject: [PATCH] Add split database and ACL binaries for modular deployment (v0.54.0) - Split orly-db into orly-db-badger and orly-db-neo4j backends - Split orly-acl into orly-acl-follows, orly-acl-managed, orly-acl-curation - Add shared pkg/database/server/ for gRPC database service - Add shared pkg/acl/server/ for gRPC ACL service - Add pkg/acl/grpc/ client for relay-to-ACL communication - Add gRPC proto definitions for ACL service (pkg/proto/orlyacl/) - Update launcher to compute binary names from backend/mode settings - When ACL disabled, relay runs in open mode (no restrictions) - Add Makefile with all-split, arm64-split, and per-binary targets - Include systemd service file for split IPC deployment Files modified: - Makefile: New build system with split binary targets - app/config/config.go: Add ACL gRPC client config options - cmd/orly-acl/: Legacy monolithic ACL server - cmd/orly-acl-curation/main.go: Curation mode binary - cmd/orly-acl-follows/main.go: Follows mode binary - cmd/orly-acl-managed/main.go: Managed mode binary - cmd/orly-db-badger/main.go: Badger backend binary - cmd/orly-db-neo4j/main.go: Neo4j backend binary - cmd/orly-launcher/config.go: Add DBBackend, compute binary names - cmd/orly-launcher/supervisor.go: Handle no-ACL mode, add ACL health check - main.go: Add gRPC ACL client initialization - orly.service: Systemd service for split IPC mode - pkg/acl/acl.go: Add gRPC ACL interface type - pkg/acl/grpc/client.go: gRPC ACL client implementation - pkg/acl/server/: Shared ACL gRPC server package - pkg/database/server/: Shared database gRPC server package - pkg/proto/orlyacl/: ACL service protobuf definitions - pkg/version/version: v0.54.0 - proto/orlyacl/: ACL proto source files Co-Authored-By: Claude Opus 4.5 --- Makefile | 194 ++ app/config/config.go | 18 + cmd/orly-acl-curation/main.go | 163 ++ cmd/orly-acl-follows/main.go | 175 ++ cmd/orly-acl-managed/main.go | 138 ++ cmd/orly-acl/config.go | 112 + cmd/orly-acl/main.go | 167 ++ cmd/orly-acl/service.go | 788 +++++++ cmd/orly-db-badger/main.go | 122 + cmd/orly-db-neo4j/main.go | 108 + cmd/orly-launcher/config.go | 52 +- cmd/orly-launcher/supervisor.go | 131 +- main.go | 36 +- orly.service | 66 + pkg/acl/acl.go | 7 + pkg/acl/grpc/client.go | 384 ++++ pkg/acl/server/config.go | 32 + pkg/acl/server/server.go | 144 ++ pkg/acl/server/service.go | 788 +++++++ pkg/database/server/config.go | 33 + pkg/database/server/server.go | 111 + pkg/database/server/service.go | 731 ++++++ pkg/proto/orlyacl/v1/acl.pb.go | 250 +++ pkg/proto/orlyacl/v1/acl_grpc.pb.go | 1887 ++++++++++++++++ pkg/proto/orlyacl/v1/types.pb.go | 3234 +++++++++++++++++++++++++++ pkg/version/version | 2 +- proto/orlyacl/v1/acl.proto | 151 ++ proto/orlyacl/v1/types.proto | 292 +++ 28 files changed, 10294 insertions(+), 22 deletions(-) create mode 100644 Makefile create mode 100644 cmd/orly-acl-curation/main.go create mode 100644 cmd/orly-acl-follows/main.go create mode 100644 cmd/orly-acl-managed/main.go create mode 100644 cmd/orly-acl/config.go create mode 100644 cmd/orly-acl/main.go create mode 100644 cmd/orly-acl/service.go create mode 100644 cmd/orly-db-badger/main.go create mode 100644 cmd/orly-db-neo4j/main.go create mode 100644 orly.service create mode 100644 pkg/acl/grpc/client.go create mode 100644 pkg/acl/server/config.go create mode 100644 pkg/acl/server/server.go create mode 100644 pkg/acl/server/service.go create mode 100644 pkg/database/server/config.go create mode 100644 pkg/database/server/server.go create mode 100644 pkg/database/server/service.go create mode 100644 pkg/proto/orlyacl/v1/acl.pb.go create mode 100644 pkg/proto/orlyacl/v1/acl_grpc.pb.go create mode 100644 pkg/proto/orlyacl/v1/types.pb.go create mode 100644 proto/orlyacl/v1/acl.proto create mode 100644 proto/orlyacl/v1/types.proto diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..26fb3b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,194 @@ +# ORLY Nostr Relay Build System +.PHONY: all orly orly-db orly-acl orly-launcher proto clean test deploy web install help +.PHONY: orly-db-badger orly-db-neo4j orly-acl-follows orly-acl-managed orly-acl-curation +.PHONY: all-split arm64-split install-split + +# Build flags +CGO_ENABLED ?= 0 +GOOS ?= $(shell go env GOOS) +GOARCH ?= $(shell go env GOARCH) +BUILD_FLAGS = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) + +# Binaries +BIN_DIR = . +ORLY = $(BIN_DIR)/orly +ORLY_LAUNCHER = $(BIN_DIR)/orly-launcher + +# Legacy monolithic binaries (for backwards compatibility) +ORLY_DB = $(BIN_DIR)/orly-db +ORLY_ACL = $(BIN_DIR)/orly-acl + +# Split database backends +ORLY_DB_BADGER = $(BIN_DIR)/orly-db-badger +ORLY_DB_NEO4J = $(BIN_DIR)/orly-db-neo4j + +# Split ACL modes +ORLY_ACL_FOLLOWS = $(BIN_DIR)/orly-acl-follows +ORLY_ACL_MANAGED = $(BIN_DIR)/orly-acl-managed +ORLY_ACL_CURATION = $(BIN_DIR)/orly-acl-curation + +# === Default Targets (Legacy) === + +# Default target: build everything (legacy monolithic) +all: orly orly-db orly-launcher + @echo "All binaries built successfully" + +# Build everything including ACL (when proto exists) +all-acl: proto orly orly-db orly-acl orly-launcher + @echo "All binaries (including ACL) built successfully" + +# === Split Binaries (New) === + +# Build split mode: orly + orly-db-badger + orly-acl-follows + launcher +all-split: proto orly orly-db-badger orly-acl-follows orly-launcher + @echo "Split mode binaries built successfully" + +# Build all split binaries (all backends and all ACL modes) +all-backends: proto orly orly-db-badger orly-db-neo4j orly-acl-follows orly-acl-managed orly-acl-curation orly-launcher + @echo "All backend and ACL mode binaries built successfully" + +# Main relay binary +orly: + $(BUILD_FLAGS) go build -o $(ORLY) . + +# === Database Backends === + +# Legacy monolithic database server +orly-db: + $(BUILD_FLAGS) go build -o $(ORLY_DB) ./cmd/orly-db + +# Badger database server +orly-db-badger: + $(BUILD_FLAGS) go build -o $(ORLY_DB_BADGER) ./cmd/orly-db-badger + +# Neo4j database server +orly-db-neo4j: + $(BUILD_FLAGS) go build -o $(ORLY_DB_NEO4J) ./cmd/orly-db-neo4j + +# === ACL Modes === + +# Legacy monolithic ACL server (requires proto generation first) +orly-acl: + $(BUILD_FLAGS) go build -o $(ORLY_ACL) ./cmd/orly-acl + +# Follows ACL server (whitelist based on admin follows) +orly-acl-follows: + $(BUILD_FLAGS) go build -o $(ORLY_ACL_FOLLOWS) ./cmd/orly-acl-follows + +# Managed ACL server (NIP-86 fine-grained control) +orly-acl-managed: + $(BUILD_FLAGS) go build -o $(ORLY_ACL_MANAGED) ./cmd/orly-acl-managed + +# Curation ACL server (rate-limited trust tiers) +orly-acl-curation: + $(BUILD_FLAGS) go build -o $(ORLY_ACL_CURATION) ./cmd/orly-acl-curation + +# Process supervisor/launcher +orly-launcher: + $(BUILD_FLAGS) go build -o $(ORLY_LAUNCHER) ./cmd/orly-launcher + +# Generate protobuf code +proto: + cd proto && buf generate + +# === Cross-Compile for ARM64 === + +# Build for ARM64 (relay.orly.dev deployment) - legacy +arm64: + $(MAKE) GOOS=linux GOARCH=arm64 all + +# Build everything for ARM64 including ACL - legacy +arm64-acl: + $(MAKE) GOOS=linux GOARCH=arm64 all-acl + +# Build split mode for ARM64 (recommended for relay.orly.dev) +arm64-split: + $(MAKE) GOOS=linux GOARCH=arm64 all-split + +# Build all backends for ARM64 +arm64-backends: + $(MAKE) GOOS=linux GOARCH=arm64 all-backends + +# === Other Targets === + +# Build web UI and embed +web: + ./scripts/update-embedded-web.sh + +# Clean build artifacts +clean: + rm -f $(ORLY) $(ORLY_DB) $(ORLY_ACL) $(ORLY_LAUNCHER) + rm -f $(ORLY_DB_BADGER) $(ORLY_DB_NEO4J) + rm -f $(ORLY_ACL_FOLLOWS) $(ORLY_ACL_MANAGED) $(ORLY_ACL_CURATION) + rm -f orly-db-arm64 orly-acl-arm64 orly-launcher-arm64 next.orly.dev + +# Run tests +test: + ./scripts/test.sh + +# Deploy to relay.orly.dev (builds on remote) - legacy +deploy: + ssh relay.orly.dev 'cd ~/src/next.orly.dev && git pull origin main && make all && sudo /usr/sbin/setcap cap_net_bind_service=+ep ~/.local/bin/next.orly.dev && sudo systemctl restart orly' + +# Deploy with ACL server - legacy +deploy-acl: + ssh relay.orly.dev 'cd ~/src/next.orly.dev && git pull origin main && make all-acl && sudo /usr/sbin/setcap cap_net_bind_service=+ep ~/.local/bin/next.orly.dev && sudo systemctl restart orly' + +# Deploy split mode (recommended) +deploy-split: + ssh relay.orly.dev 'cd ~/src/next.orly.dev && git pull origin main && make all-split && sudo /usr/sbin/setcap cap_net_bind_service=+ep ~/.local/bin/next.orly.dev && sudo systemctl restart orly' + +# Install all binaries locally - legacy +install: all + mkdir -p ~/.local/bin + cp $(ORLY) $(ORLY_DB) $(ORLY_LAUNCHER) ~/.local/bin/ + +# Install including ACL - legacy +install-acl: all-acl + mkdir -p ~/.local/bin + cp $(ORLY) $(ORLY_DB) $(ORLY_ACL) $(ORLY_LAUNCHER) ~/.local/bin/ + +# Install split mode binaries +install-split: all-split + mkdir -p ~/.local/bin + cp $(ORLY) $(ORLY_DB_BADGER) $(ORLY_ACL_FOLLOWS) $(ORLY_LAUNCHER) ~/.local/bin/ + +# Install all backends and modes +install-backends: all-backends + mkdir -p ~/.local/bin + cp $(ORLY) $(ORLY_DB_BADGER) $(ORLY_DB_NEO4J) $(ORLY_ACL_FOLLOWS) $(ORLY_ACL_MANAGED) $(ORLY_ACL_CURATION) $(ORLY_LAUNCHER) ~/.local/bin/ + +# Help +help: + @echo "ORLY Build Targets:" + @echo "" + @echo " Split Mode (Recommended):" + @echo " all-split - Build orly + orly-db-badger + orly-acl-follows + launcher" + @echo " all-backends - Build all database backends and ACL modes" + @echo " arm64-split - Cross-compile split mode for ARM64" + @echo " deploy-split - Deploy split mode to relay.orly.dev" + @echo " install-split - Install split mode to ~/.local/bin/" + @echo "" + @echo " Database Backends:" + @echo " orly-db-badger - Build Badger database server" + @echo " orly-db-neo4j - Build Neo4j database server" + @echo "" + @echo " ACL Modes:" + @echo " orly-acl-follows - Build Follows ACL server (whitelist)" + @echo " orly-acl-managed - Build Managed ACL server (NIP-86)" + @echo " orly-acl-curation - Build Curation ACL server (rate limits)" + @echo "" + @echo " Legacy (Monolithic):" + @echo " all - Build orly + orly-db + launcher" + @echo " all-acl - Build all including orly-acl" + @echo " orly-db - Build monolithic database server" + @echo " orly-acl - Build monolithic ACL server" + @echo "" + @echo " Core:" + @echo " orly - Build main relay binary" + @echo " orly-launcher - Build process supervisor" + @echo " proto - Generate protobuf code" + @echo " web - Rebuild embedded web UI" + @echo " test - Run test suite" + @echo " clean - Remove build artifacts" + @echo " help - Show this help" diff --git a/app/config/config.go b/app/config/config.go index f1d0436..38e53b6 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -123,6 +123,11 @@ type C struct { GRPCServerAddress string `env:"ORLY_GRPC_SERVER" usage:"address of remote gRPC database server (only used when ORLY_DB_TYPE=grpc)"` GRPCConnectTimeout time.Duration `env:"ORLY_GRPC_CONNECT_TIMEOUT" default:"10s" usage:"gRPC connection timeout (only used when ORLY_DB_TYPE=grpc)"` + // gRPC ACL client settings (only used when ORLY_ACL_TYPE=grpc) + ACLType string `env:"ORLY_ACL_TYPE" default:"local" usage:"ACL backend: local (in-process) or grpc (remote ACL server)"` + GRPCACLServerAddress string `env:"ORLY_GRPC_ACL_SERVER" usage:"address of remote gRPC ACL server (only used when ORLY_ACL_TYPE=grpc)"` + GRPCACLConnectTimeout time.Duration `env:"ORLY_GRPC_ACL_TIMEOUT" default:"10s" usage:"gRPC ACL connection timeout (only used when ORLY_ACL_TYPE=grpc)"` + QueryCacheSizeMB int `env:"ORLY_QUERY_CACHE_SIZE_MB" default:"512" usage:"query cache size in MB (caches database query results for faster REQ responses)"` QueryCacheMaxAge string `env:"ORLY_QUERY_CACHE_MAX_AGE" default:"5m" usage:"maximum age for cached query results (e.g., 5m, 10m, 1h)"` @@ -843,3 +848,16 @@ func (cfg *C) GetGRPCConfigValues() ( return cfg.GRPCServerAddress, cfg.GRPCConnectTimeout } + +// GetGRPCACLConfigValues returns the gRPC ACL client configuration values. +// This avoids circular imports with pkg/acl/grpc while allowing main.go to construct +// the gRPC ACL client configuration. +func (cfg *C) GetGRPCACLConfigValues() ( + aclType string, + serverAddress string, + connectTimeout time.Duration, +) { + return cfg.ACLType, + cfg.GRPCACLServerAddress, + cfg.GRPCACLConnectTimeout +} diff --git a/cmd/orly-acl-curation/main.go b/cmd/orly-acl-curation/main.go new file mode 100644 index 0000000..114a004 --- /dev/null +++ b/cmd/orly-acl-curation/main.go @@ -0,0 +1,163 @@ +// orly-acl-curation is a standalone gRPC ACL server using the Curating mode. +// It provides three-tier classification: trusted, blacklisted, and unclassified (rate-limited). +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "time" + + "go-simpler.org/env" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/acl/server" + "next.orly.dev/pkg/database" + databasegrpc "next.orly.dev/pkg/database/grpc" +) + +// Config holds the ACL server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_ACL_LISTEN" default:"127.0.0.1:50052" usage:"gRPC server listen address"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_ACL_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Database configuration + DBType string `env:"ORLY_ACL_DB_TYPE" default:"grpc" usage:"database type: badger or grpc"` + GRPCDBServer string `env:"ORLY_ACL_GRPC_DB_SERVER" usage:"gRPC database server address (when DB_TYPE=grpc)"` + DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory (when DB_TYPE=badger)"` + + // Badger configuration (when DB_TYPE=badger) + BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"256" usage:"block cache size in MB"` + IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"128" usage:"index cache size in MB"` + ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level"` + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"64" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"` + SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"` + + // ACL configuration + Owners string `env:"ORLY_OWNERS" usage:"comma-separated list of owner npubs"` + Admins string `env:"ORLY_ADMINS" usage:"comma-separated list of admin npubs"` + RelayAddresses string `env:"ORLY_RELAY_ADDRESSES" usage:"comma-separated list of relay addresses (self)"` +} + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-acl-curation starting with log level: %s", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Initialize database (direct Badger or gRPC client) + var db database.Database + var err error + var ownsDB bool + + if cfg.DBType == "grpc" { + // Use gRPC database client + log.I.F("connecting to gRPC database server at %s", cfg.GRPCDBServer) + db, err = databasegrpc.New(ctx, &databasegrpc.ClientConfig{ + ServerAddress: cfg.GRPCDBServer, + ConnectTimeout: 30 * time.Second, + }) + if chk.E(err) { + log.E.F("failed to connect to gRPC database: %v", err) + os.Exit(1) + } + ownsDB = false // gRPC client doesn't own the database + } else { + // Use direct Badger database + dbCfg := &database.DatabaseConfig{ + DataDir: cfg.DataDir, + LogLevel: cfg.LogLevel, + BlockCacheMB: cfg.BlockCacheMB, + IndexCacheMB: cfg.IndexCacheMB, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + SerialCachePubkeys: cfg.SerialCachePubkeys, + SerialCacheEventIds: cfg.SerialCacheEventIds, + ZSTDLevel: cfg.ZSTDLevel, + } + + log.I.F("initializing Badger database at %s", cfg.DataDir) + db, err = database.NewWithConfig(ctx, cancel, dbCfg) + if chk.E(err) { + log.E.F("failed to initialize database: %v", err) + os.Exit(1) + } + ownsDB = true + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create server config + serverCfg := &server.Config{ + Listen: cfg.Listen, + ACLMode: "curating", // Hardcoded for this binary + LogLevel: cfg.LogLevel, + Owners: splitList(cfg.Owners), + Admins: splitList(cfg.Admins), + RelayAddresses: splitList(cfg.RelayAddresses), + } + + // Create and configure server + srv := server.New(db, serverCfg, ownsDB) + if err := srv.ConfigureACL(ctx); chk.E(err) { + log.E.F("failed to configure ACL: %v", err) + os.Exit(1) + } + + // Start server + if err := srv.ListenAndServe(ctx, cancel); err != nil { + log.E.F("gRPC server error: %v", err) + } +} + +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + // Set default data directory if not specified + if cfg.DataDir == "" { + home, err := os.UserHomeDir() + if chk.E(err) { + log.E.F("failed to get home directory: %v", err) + os.Exit(1) + } + cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY") + } + + // Ensure data directory exists (for badger mode) + if cfg.DBType == "badger" || cfg.DBType == "" { + if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) { + log.E.F("failed to create data directory %s: %v", cfg.DataDir, err) + os.Exit(1) + } + } + + return cfg +} + +func splitList(s string) []string { + if s == "" { + return nil + } + return strings.Split(s, ",") +} diff --git a/cmd/orly-acl-follows/main.go b/cmd/orly-acl-follows/main.go new file mode 100644 index 0000000..d054a4c --- /dev/null +++ b/cmd/orly-acl-follows/main.go @@ -0,0 +1,175 @@ +// orly-acl-follows is a standalone gRPC ACL server using the Follows mode. +// It whitelists users who are followed by the relay admins. +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "time" + + "go-simpler.org/env" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/acl/server" + "next.orly.dev/pkg/database" + databasegrpc "next.orly.dev/pkg/database/grpc" +) + +// Config holds the ACL server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_ACL_LISTEN" default:"127.0.0.1:50052" usage:"gRPC server listen address"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_ACL_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Database configuration + DBType string `env:"ORLY_ACL_DB_TYPE" default:"grpc" usage:"database type: badger or grpc"` + GRPCDBServer string `env:"ORLY_ACL_GRPC_DB_SERVER" usage:"gRPC database server address (when DB_TYPE=grpc)"` + DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory (when DB_TYPE=badger)"` + + // Badger configuration (when DB_TYPE=badger) + BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"256" usage:"block cache size in MB"` + IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"128" usage:"index cache size in MB"` + ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level"` + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"64" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"` + SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"` + + // ACL configuration + Owners string `env:"ORLY_OWNERS" usage:"comma-separated list of owner npubs"` + Admins string `env:"ORLY_ADMINS" usage:"comma-separated list of admin npubs"` + BootstrapRelays string `env:"ORLY_BOOTSTRAP_RELAYS" usage:"comma-separated list of bootstrap relays"` + RelayAddresses string `env:"ORLY_RELAY_ADDRESSES" usage:"comma-separated list of relay addresses (self)"` + + // Follows ACL configuration + FollowListFrequency time.Duration `env:"ORLY_FOLLOW_LIST_FREQUENCY" default:"1h" usage:"follow list sync frequency"` + FollowsThrottleEnabled bool `env:"ORLY_FOLLOWS_THROTTLE_ENABLED" default:"false" usage:"enable progressive throttle for non-followed users"` + FollowsThrottlePerEvent time.Duration `env:"ORLY_FOLLOWS_THROTTLE_PER_EVENT" default:"25ms" usage:"throttle delay increment per event"` + FollowsThrottleMaxDelay time.Duration `env:"ORLY_FOLLOWS_THROTTLE_MAX_DELAY" default:"60s" usage:"maximum throttle delay"` +} + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-acl-follows starting with log level: %s", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Initialize database (direct Badger or gRPC client) + var db database.Database + var err error + var ownsDB bool + + if cfg.DBType == "grpc" { + // Use gRPC database client + log.I.F("connecting to gRPC database server at %s", cfg.GRPCDBServer) + db, err = databasegrpc.New(ctx, &databasegrpc.ClientConfig{ + ServerAddress: cfg.GRPCDBServer, + ConnectTimeout: 30 * time.Second, + }) + if chk.E(err) { + log.E.F("failed to connect to gRPC database: %v", err) + os.Exit(1) + } + ownsDB = false // gRPC client doesn't own the database + } else { + // Use direct Badger database + dbCfg := &database.DatabaseConfig{ + DataDir: cfg.DataDir, + LogLevel: cfg.LogLevel, + BlockCacheMB: cfg.BlockCacheMB, + IndexCacheMB: cfg.IndexCacheMB, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + SerialCachePubkeys: cfg.SerialCachePubkeys, + SerialCacheEventIds: cfg.SerialCacheEventIds, + ZSTDLevel: cfg.ZSTDLevel, + } + + log.I.F("initializing Badger database at %s", cfg.DataDir) + db, err = database.NewWithConfig(ctx, cancel, dbCfg) + if chk.E(err) { + log.E.F("failed to initialize database: %v", err) + os.Exit(1) + } + ownsDB = true + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create server config + serverCfg := &server.Config{ + Listen: cfg.Listen, + ACLMode: "follows", // Hardcoded for this binary + LogLevel: cfg.LogLevel, + Owners: splitList(cfg.Owners), + Admins: splitList(cfg.Admins), + BootstrapRelays: splitList(cfg.BootstrapRelays), + RelayAddresses: splitList(cfg.RelayAddresses), + FollowListFrequency: cfg.FollowListFrequency, + FollowsThrottleEnabled: cfg.FollowsThrottleEnabled, + FollowsThrottlePerEvent: cfg.FollowsThrottlePerEvent, + FollowsThrottleMaxDelay: cfg.FollowsThrottleMaxDelay, + } + + // Create and configure server + srv := server.New(db, serverCfg, ownsDB) + if err := srv.ConfigureACL(ctx); chk.E(err) { + log.E.F("failed to configure ACL: %v", err) + os.Exit(1) + } + + // Start server + if err := srv.ListenAndServe(ctx, cancel); err != nil { + log.E.F("gRPC server error: %v", err) + } +} + +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + // Set default data directory if not specified + if cfg.DataDir == "" { + home, err := os.UserHomeDir() + if chk.E(err) { + log.E.F("failed to get home directory: %v", err) + os.Exit(1) + } + cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY") + } + + // Ensure data directory exists (for badger mode) + if cfg.DBType == "badger" { + if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) { + log.E.F("failed to create data directory %s: %v", cfg.DataDir, err) + os.Exit(1) + } + } + + return cfg +} + +func splitList(s string) []string { + if s == "" { + return nil + } + return strings.Split(s, ",") +} diff --git a/cmd/orly-acl-managed/main.go b/cmd/orly-acl-managed/main.go new file mode 100644 index 0000000..1fd219f --- /dev/null +++ b/cmd/orly-acl-managed/main.go @@ -0,0 +1,138 @@ +// orly-acl-managed is a standalone gRPC ACL server using the Managed mode. +// It provides fine-grained control via NIP-86 management API. +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "time" + + "go-simpler.org/env" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/acl/server" + "next.orly.dev/pkg/database" +) + +// Config holds the ACL server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_ACL_LISTEN" default:"127.0.0.1:50052" usage:"gRPC server listen address"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_ACL_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Database configuration - Managed mode requires direct Badger access + DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory"` + + // Badger configuration + BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"256" usage:"block cache size in MB"` + IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"128" usage:"index cache size in MB"` + ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level"` + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"64" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"` + SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"` + + // ACL configuration + Owners string `env:"ORLY_OWNERS" usage:"comma-separated list of owner npubs"` + Admins string `env:"ORLY_ADMINS" usage:"comma-separated list of admin npubs"` + RelayAddresses string `env:"ORLY_RELAY_ADDRESSES" usage:"comma-separated list of relay addresses (self)"` +} + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-acl-managed starting with log level: %s", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Managed mode requires direct Badger database access (not gRPC) + dbCfg := &database.DatabaseConfig{ + DataDir: cfg.DataDir, + LogLevel: cfg.LogLevel, + BlockCacheMB: cfg.BlockCacheMB, + IndexCacheMB: cfg.IndexCacheMB, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + SerialCachePubkeys: cfg.SerialCachePubkeys, + SerialCacheEventIds: cfg.SerialCacheEventIds, + ZSTDLevel: cfg.ZSTDLevel, + } + + log.I.F("initializing Badger database at %s", cfg.DataDir) + db, err := database.NewWithConfig(ctx, cancel, dbCfg) + if chk.E(err) { + log.E.F("failed to initialize database: %v", err) + os.Exit(1) + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create server config + serverCfg := &server.Config{ + Listen: cfg.Listen, + ACLMode: "managed", // Hardcoded for this binary + LogLevel: cfg.LogLevel, + Owners: splitList(cfg.Owners), + Admins: splitList(cfg.Admins), + RelayAddresses: splitList(cfg.RelayAddresses), + } + + // Create and configure server + srv := server.New(db, serverCfg, true) + if err := srv.ConfigureACL(ctx); chk.E(err) { + log.E.F("failed to configure ACL: %v", err) + os.Exit(1) + } + + // Start server + if err := srv.ListenAndServe(ctx, cancel); err != nil { + log.E.F("gRPC server error: %v", err) + } +} + +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + // Set default data directory if not specified + if cfg.DataDir == "" { + home, err := os.UserHomeDir() + if chk.E(err) { + log.E.F("failed to get home directory: %v", err) + os.Exit(1) + } + cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY") + } + + // Ensure data directory exists + if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) { + log.E.F("failed to create data directory %s: %v", cfg.DataDir, err) + os.Exit(1) + } + + return cfg +} + +func splitList(s string) []string { + if s == "" { + return nil + } + return strings.Split(s, ",") +} diff --git a/cmd/orly-acl/config.go b/cmd/orly-acl/config.go new file mode 100644 index 0000000..5bc2ac0 --- /dev/null +++ b/cmd/orly-acl/config.go @@ -0,0 +1,112 @@ +package main + +import ( + "os" + "path/filepath" + "strings" + "time" + + "go-simpler.org/env" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" +) + +// Config holds the ACL server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_ACL_LISTEN" default:"127.0.0.1:50052" usage:"gRPC server listen address"` + + // ACLMode is the active ACL mode (none, follows, managed, curating) + ACLMode string `env:"ORLY_ACL_MODE" default:"none" usage:"ACL mode: none, follows, managed, curating"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_ACL_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Database configuration + DBType string `env:"ORLY_ACL_DB_TYPE" default:"badger" usage:"database type: badger or grpc"` + GRPCDBServer string `env:"ORLY_ACL_GRPC_DB_SERVER" usage:"gRPC database server address (when DB_TYPE=grpc)"` + DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory (when DB_TYPE=badger)"` + + // Badger configuration (when DB_TYPE=badger) + BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"1024" usage:"block cache size in MB"` + IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"512" usage:"index cache size in MB"` + ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level"` + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"256" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"` + SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"` + + // ACL configuration + Owners string `env:"ORLY_OWNERS" usage:"comma-separated list of owner npubs"` + Admins string `env:"ORLY_ADMINS" usage:"comma-separated list of admin npubs"` + BootstrapRelays string `env:"ORLY_BOOTSTRAP_RELAYS" usage:"comma-separated list of bootstrap relays"` + RelayAddresses string `env:"ORLY_RELAY_ADDRESSES" usage:"comma-separated list of relay addresses (self)"` + + // Follows ACL configuration + FollowListFrequency time.Duration `env:"ORLY_FOLLOW_LIST_FREQUENCY" default:"1h" usage:"follow list sync frequency"` + FollowsThrottleEnabled bool `env:"ORLY_FOLLOWS_THROTTLE_ENABLED" default:"false" usage:"enable progressive throttle for non-followed users"` + FollowsThrottlePerEvent time.Duration `env:"ORLY_FOLLOWS_THROTTLE_PER_EVENT" default:"25ms" usage:"throttle delay increment per event"` + FollowsThrottleMaxDelay time.Duration `env:"ORLY_FOLLOWS_THROTTLE_MAX_DELAY" default:"60s" usage:"maximum throttle delay"` +} + +// loadConfig loads configuration from environment variables. +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + // Set default data directory if not specified + if cfg.DataDir == "" { + home, err := os.UserHomeDir() + if chk.E(err) { + log.E.F("failed to get home directory: %v", err) + os.Exit(1) + } + cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY") + } + + // Ensure data directory exists (for badger mode) + if cfg.DBType == "badger" { + if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) { + log.E.F("failed to create data directory %s: %v", cfg.DataDir, err) + os.Exit(1) + } + } + + return cfg +} + +// GetOwners returns the list of owner pubkeys +func (c *Config) GetOwners() []string { + if c.Owners == "" { + return nil + } + return strings.Split(c.Owners, ",") +} + +// GetAdmins returns the list of admin pubkeys +func (c *Config) GetAdmins() []string { + if c.Admins == "" { + return nil + } + return strings.Split(c.Admins, ",") +} + +// GetBootstrapRelays returns the list of bootstrap relays +func (c *Config) GetBootstrapRelays() []string { + if c.BootstrapRelays == "" { + return nil + } + return strings.Split(c.BootstrapRelays, ",") +} + +// GetRelayAddresses returns the list of relay addresses (self) +func (c *Config) GetRelayAddresses() []string { + if c.RelayAddresses == "" { + return nil + } + return strings.Split(c.RelayAddresses, ",") +} diff --git a/cmd/orly-acl/main.go b/cmd/orly-acl/main.go new file mode 100644 index 0000000..11ee2db --- /dev/null +++ b/cmd/orly-acl/main.go @@ -0,0 +1,167 @@ +// orly-acl is a standalone gRPC ACL server for the ORLY relay. +// It wraps the ACL implementations and exposes them via gRPC. +package main + +import ( + "context" + "net" + "os" + "os/signal" + "syscall" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/app/config" + "next.orly.dev/pkg/acl" + "next.orly.dev/pkg/database" + databasegrpc "next.orly.dev/pkg/database/grpc" + orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1" +) + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-acl starting with log level: %s, mode: %s", cfg.LogLevel, cfg.ACLMode) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Initialize database (direct Badger or gRPC client) + var db database.Database + var err error + + if cfg.DBType == "grpc" { + // Use gRPC database client + log.I.F("connecting to gRPC database server at %s", cfg.GRPCDBServer) + dbClient, err := databasegrpc.New(ctx, &databasegrpc.ClientConfig{ + ServerAddress: cfg.GRPCDBServer, + ConnectTimeout: 30 * time.Second, + }) + if chk.E(err) { + log.E.F("failed to connect to gRPC database: %v", err) + os.Exit(1) + } + db = dbClient + } else { + // Use direct Badger database + dbCfg := &database.DatabaseConfig{ + DataDir: cfg.DataDir, + LogLevel: cfg.LogLevel, + BlockCacheMB: cfg.BlockCacheMB, + IndexCacheMB: cfg.IndexCacheMB, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + SerialCachePubkeys: cfg.SerialCachePubkeys, + SerialCacheEventIds: cfg.SerialCacheEventIds, + ZSTDLevel: cfg.ZSTDLevel, + } + + log.I.F("initializing Badger database at %s", cfg.DataDir) + db, err = database.NewWithConfig(ctx, cancel, dbCfg) + if chk.E(err) { + log.E.F("failed to initialize database: %v", err) + os.Exit(1) + } + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create app config for ACL configuration + appCfg := &config.C{ + Owners: cfg.GetOwners(), + Admins: cfg.GetAdmins(), + BootstrapRelays: cfg.GetBootstrapRelays(), + RelayAddresses: cfg.GetRelayAddresses(), + FollowListFrequency: cfg.FollowListFrequency, + FollowsThrottleEnabled: cfg.FollowsThrottleEnabled, + FollowsThrottlePerEvent: cfg.FollowsThrottlePerEvent, + FollowsThrottleMaxDelay: cfg.FollowsThrottleMaxDelay, + } + + // Set ACL mode and configure the registry + acl.Registry.SetMode(cfg.ACLMode) + if err := acl.Registry.Configure(appCfg, db, ctx); chk.E(err) { + log.E.F("failed to configure ACL: %v", err) + os.Exit(1) + } + + // Start the syncer goroutine for background operations + acl.Registry.Syncer() + log.I.F("ACL syncer started for mode: %s", cfg.ACLMode) + + // Create gRPC server + grpcServer := grpc.NewServer( + grpc.MaxRecvMsgSize(16<<20), // 16MB + grpc.MaxSendMsgSize(16<<20), // 16MB + ) + + // Register ACL service + service := NewACLService(cfg, db) + orlyaclv1.RegisterACLServiceServer(grpcServer, service) + + // Register reflection for debugging with grpcurl + reflection.Register(grpcServer) + + // Start listening + lis, err := net.Listen("tcp", cfg.Listen) + if chk.E(err) { + log.E.F("failed to listen on %s: %v", cfg.Listen, err) + os.Exit(1) + } + log.I.F("gRPC ACL server listening on %s", cfg.Listen) + + // Handle graceful shutdown + go func() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT) + sig := <-sigs + log.I.F("received signal %v, shutting down...", sig) + + // Cancel context to stop all operations + cancel() + + // Gracefully stop gRPC server with timeout + stopped := make(chan struct{}) + go func() { + grpcServer.GracefulStop() + close(stopped) + }() + + select { + case <-stopped: + log.I.F("gRPC server stopped gracefully") + case <-time.After(5 * time.Second): + log.W.F("gRPC graceful stop timed out, forcing stop") + grpcServer.Stop() + } + + // Sync and close database (only for direct Badger) + if cfg.DBType != "grpc" { + log.I.F("syncing database...") + if err := db.Sync(); chk.E(err) { + log.W.F("failed to sync database: %v", err) + } + log.I.F("closing database...") + if err := db.Close(); chk.E(err) { + log.W.F("failed to close database: %v", err) + } + } + log.I.F("shutdown complete") + }() + + // Serve gRPC + if err := grpcServer.Serve(lis); err != nil { + log.E.F("gRPC server error: %v", err) + } +} diff --git a/cmd/orly-acl/service.go b/cmd/orly-acl/service.go new file mode 100644 index 0000000..230c9c8 --- /dev/null +++ b/cmd/orly-acl/service.go @@ -0,0 +1,788 @@ +package main + +import ( + "context" + "encoding/hex" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/acl" + "next.orly.dev/pkg/database" + orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1" + orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1" +) + +// ACLService implements the orlyaclv1.ACLServiceServer interface. +type ACLService struct { + orlyaclv1.UnimplementedACLServiceServer + cfg *Config + db database.Database +} + +// NewACLService creates a new ACL service. +func NewACLService(cfg *Config, db database.Database) *ACLService { + return &ACLService{ + cfg: cfg, + db: db, + } +} + +// === Core ACL Methods === + +func (s *ACLService) GetAccessLevel(ctx context.Context, req *orlyaclv1.AccessLevelRequest) (*orlyaclv1.AccessLevelResponse, error) { + level := acl.Registry.GetAccessLevel(req.Pubkey, req.Address) + return &orlyaclv1.AccessLevelResponse{Level: level}, nil +} + +func (s *ACLService) CheckPolicy(ctx context.Context, req *orlyaclv1.PolicyCheckRequest) (*orlyaclv1.PolicyCheckResponse, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + allowed, err := acl.Registry.CheckPolicy(ev) + resp := &orlyaclv1.PolicyCheckResponse{Allowed: allowed} + if err != nil { + resp.Error = err.Error() + } + return resp, nil +} + +func (s *ACLService) GetACLInfo(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ACLInfoResponse, error) { + name, description, documentation := acl.Registry.GetACLInfo() + return &orlyaclv1.ACLInfoResponse{ + Name: name, + Description: description, + Documentation: documentation, + }, nil +} + +func (s *ACLService) GetMode(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ModeResponse, error) { + return &orlyaclv1.ModeResponse{Mode: acl.Registry.Type()}, nil +} + +func (s *ACLService) Ready(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ReadyResponse, error) { + // Check if database is ready + select { + case <-s.db.Ready(): + return &orlyaclv1.ReadyResponse{Ready: true}, nil + default: + return &orlyaclv1.ReadyResponse{Ready: false}, nil + } +} + +// === Follows ACL Methods === + +func (s *ACLService) GetThrottleDelay(ctx context.Context, req *orlyaclv1.ThrottleDelayRequest) (*orlyaclv1.ThrottleDelayResponse, error) { + // Get the active ACL and check if it's Follows + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + delay := follows.GetThrottleDelay(req.Pubkey, req.Ip) + return &orlyaclv1.ThrottleDelayResponse{DelayMs: delay.Milliseconds()}, nil + } + } + } + return &orlyaclv1.ThrottleDelayResponse{DelayMs: 0}, nil +} + +func (s *ACLService) AddFollow(ctx context.Context, req *orlyaclv1.AddFollowRequest) (*orlyaclv1.Empty, error) { + acl.Registry.AddFollow(req.Pubkey) + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) GetFollowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.FollowedPubkeysResponse, error) { + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + pubkeys := follows.GetFollowedPubkeys() + return &orlyaclv1.FollowedPubkeysResponse{Pubkeys: pubkeys}, nil + } + } + } + return &orlyaclv1.FollowedPubkeysResponse{}, nil +} + +func (s *ACLService) GetAdminRelays(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.AdminRelaysResponse, error) { + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + urls := follows.AdminRelays() + return &orlyaclv1.AdminRelaysResponse{Urls: urls}, nil + } + } + } + return &orlyaclv1.AdminRelaysResponse{}, nil +} + +// === Managed ACL Methods === + +func (s *ACLService) BanPubkey(ctx context.Context, req *orlyaclv1.BanPubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBannedPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to ban pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnbanPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBannedPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unban pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBannedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedPubkeysResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + banned, err := managedACL.ListBannedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list banned pubkeys: %v", err) + } + resp := &orlyaclv1.ListBannedPubkeysResponse{} + for _, b := range banned { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BannedPubkey{ + Pubkey: b.Pubkey, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowPubkey(ctx context.Context, req *orlyaclv1.AllowPubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedPubkeysResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + allowed, err := managedACL.ListAllowedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed pubkeys: %v", err) + } + resp := &orlyaclv1.ListAllowedPubkeysResponse{} + for _, a := range allowed { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.AllowedPubkey{ + Pubkey: a.Pubkey, + Reason: a.Reason, + Added: a.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BanEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBannedEvent(req.EventId, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to ban event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnbanEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBannedEvent(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unban event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBannedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedEventsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + banned, err := managedACL.ListBannedEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list banned events: %v", err) + } + resp := &orlyaclv1.ListBannedEventsResponse{} + for _, b := range banned { + resp.Events = append(resp.Events, &orlyaclv1.BannedEvent{ + EventId: b.ID, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedEvent(req.EventId, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedEvent(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedEventsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + allowed, err := managedACL.ListAllowedEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed events: %v", err) + } + resp := &orlyaclv1.ListAllowedEventsResponse{} + for _, a := range allowed { + resp.Events = append(resp.Events, &orlyaclv1.AllowedEvent{ + EventId: a.ID, + Reason: a.Reason, + Added: a.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BlockIP(ctx context.Context, req *orlyaclv1.BlockIPRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBlockedIP(req.Ip, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to block IP: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnblockIP(ctx context.Context, req *orlyaclv1.IPRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBlockedIP(req.Ip); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unblock IP: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBlockedIPs(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlockedIPsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + blocked, err := managedACL.ListBlockedIPs() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list blocked IPs: %v", err) + } + resp := &orlyaclv1.ListBlockedIPsResponse{} + for _, b := range blocked { + resp.Ips = append(resp.Ips, &orlyaclv1.BlockedIP{ + Ip: b.IP, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowKind(ctx context.Context, req *orlyaclv1.AllowKindRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedKind(int(req.Kind)); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow kind: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowKind(ctx context.Context, req *orlyaclv1.KindRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedKind(int(req.Kind)); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow kind: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedKinds(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedKindsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + kinds, err := managedACL.ListAllowedKinds() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed kinds: %v", err) + } + resp := &orlyaclv1.ListAllowedKindsResponse{} + for _, k := range kinds { + resp.Kinds = append(resp.Kinds, int32(k)) + } + return resp, nil +} + +func (s *ACLService) UpdatePeerAdmins(ctx context.Context, req *orlyaclv1.UpdatePeerAdminsRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managed.UpdatePeerAdmins(req.PeerPubkeys) + return &orlyaclv1.Empty{}, nil +} + +// === Curating ACL Methods === + +func (s *ACLService) TrustPubkey(ctx context.Context, req *orlyaclv1.TrustPubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.TrustPubkey(req.Pubkey, req.Note); err != nil { + return nil, status.Errorf(codes.Internal, "failed to trust pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UntrustPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.UntrustPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to untrust pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListTrustedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListTrustedPubkeysResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + trusted, err := curatingACL.ListTrustedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list trusted pubkeys: %v", err) + } + resp := &orlyaclv1.ListTrustedPubkeysResponse{} + for _, t := range trusted { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.TrustedPubkey{ + Pubkey: t.Pubkey, + Note: t.Note, + Added: t.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BlacklistPubkey(ctx context.Context, req *orlyaclv1.BlacklistPubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.BlacklistPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to blacklist pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnblacklistPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.UnblacklistPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unblacklist pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBlacklistedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlacklistedPubkeysResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + blacklisted, err := curatingACL.ListBlacklistedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list blacklisted pubkeys: %v", err) + } + resp := &orlyaclv1.ListBlacklistedPubkeysResponse{} + for _, b := range blacklisted { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BlacklistedPubkey{ + Pubkey: b.Pubkey, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) MarkSpam(ctx context.Context, req *orlyaclv1.MarkSpamRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + if err := curatingACL.MarkEventAsSpam(req.EventId, req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to mark spam: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnmarkSpam(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + if err := curatingACL.UnmarkEventAsSpam(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unmark spam: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListSpamEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListSpamEventsResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + spam, err := curatingACL.ListSpamEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list spam events: %v", err) + } + resp := &orlyaclv1.ListSpamEventsResponse{} + for _, se := range spam { + resp.Events = append(resp.Events, &orlyaclv1.SpamEvent{ + EventId: se.EventID, + Pubkey: se.Pubkey, + Reason: se.Reason, + Added: se.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) RateLimitCheck(ctx context.Context, req *orlyaclv1.RateLimitCheckRequest) (*orlyaclv1.RateLimitCheckResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + allowed, message, err := curating.RateLimitCheck(req.Pubkey, req.Ip) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to check rate limit: %v", err) + } + return &orlyaclv1.RateLimitCheckResponse{ + Allowed: allowed, + Message: message, + }, nil +} + +func (s *ACLService) ProcessConfigEvent(ctx context.Context, req *orlyaclv1.ConfigEventRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + ev := orlydbv1.ProtoToEvent(req.Event) + if err := curating.ProcessConfigEvent(ev); err != nil { + return nil, status.Errorf(codes.Internal, "failed to process config event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) GetCuratingConfig(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.CuratingConfig, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + config, err := curating.GetConfig() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get config: %v", err) + } + resp := &orlyaclv1.CuratingConfig{ + ConfigEventId: config.ConfigEventID, + ConfigPubkey: config.ConfigPubkey, + ConfiguredAt: config.ConfiguredAt, + DailyLimit: int32(config.DailyLimit), + IpDailyLimit: int32(config.IPDailyLimit), + FirstBanHours: int32(config.FirstBanHours), + SecondBanHours: int32(config.SecondBanHours), + KindCategories: config.KindCategories, + AllowedRanges: config.AllowedRanges, + } + for _, k := range config.AllowedKinds { + resp.AllowedKinds = append(resp.AllowedKinds, int32(k)) + } + return resp, nil +} + +func (s *ACLService) IsCuratingConfigured(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.BoolResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return &orlyaclv1.BoolResponse{Value: false}, nil + } + configured, err := curating.IsConfigured() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to check if configured: %v", err) + } + return &orlyaclv1.BoolResponse{Value: configured}, nil +} + +func (s *ACLService) ListUnclassifiedUsers(ctx context.Context, req *orlyaclv1.PaginationRequest) (*orlyaclv1.ListUnclassifiedUsersResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + // The underlying ListUnclassifiedUsers only takes limit, not offset + // We'll request limit+offset and skip the first offset items + limit := int(req.Limit) + offset := int(req.Offset) + if limit == 0 { + limit = 100 // Default limit + } + users, err := curatingACL.ListUnclassifiedUsers(limit + offset) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list unclassified users: %v", err) + } + // Apply offset + if offset > 0 && len(users) > offset { + users = users[offset:] + } else if offset > 0 { + users = nil + } + // Apply limit + if limit > 0 && len(users) > limit { + users = users[:limit] + } + resp := &orlyaclv1.ListUnclassifiedUsersResponse{Total: int32(len(users))} + for _, u := range users { + resp.Users = append(resp.Users, &orlyaclv1.UnclassifiedUser{ + Pubkey: u.Pubkey, + EventCount: int32(u.EventCount), + FirstSeen: u.LastEvent.Format("2006-01-02T15:04:05Z"), + }) + } + return resp, nil +} + +func (s *ACLService) GetEventsForPubkey(ctx context.Context, req *orlyaclv1.GetEventsForPubkeyRequest) (*orlyaclv1.EventsForPubkeyResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + events, total, err := curatingACL.GetEventsForPubkey(req.Pubkey, int(req.Limit), int(req.Offset)) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get events for pubkey: %v", err) + } + resp := &orlyaclv1.EventsForPubkeyResponse{Total: int32(total)} + for _, ev := range events { + resp.Events = append(resp.Events, &orlyaclv1.EventSummary{ + Id: ev.ID, + Kind: uint32(ev.Kind), + Content: []byte(ev.Content), + CreatedAt: ev.CreatedAt, + }) + } + return resp, nil +} + +func (s *ACLService) DeleteEventsForPubkey(ctx context.Context, req *orlyaclv1.DeleteEventsForPubkeyRequest) (*orlyaclv1.DeleteCountResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + count, err := curatingACL.DeleteEventsForPubkey(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to delete events for pubkey: %v", err) + } + return &orlyaclv1.DeleteCountResponse{Count: int32(count)}, nil +} + +func (s *ACLService) ScanAllPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ScanResultResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + result, err := curatingACL.ScanAllPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to scan all pubkeys: %v", err) + } + return &orlyaclv1.ScanResultResponse{ + TotalPubkeys: int32(result.TotalPubkeys), + TotalEvents: int32(result.TotalEvents), + }, nil +} + +// === Helper Methods === + +func (s *ACLService) getManagedACL() *acl.Managed { + for _, i := range acl.Registry.ACL { + if i.Type() == "managed" { + if managed, ok := i.(*acl.Managed); ok { + return managed + } + } + } + return nil +} + +func (s *ACLService) getCuratingACL() *acl.Curating { + for _, i := range acl.Registry.ACL { + if i.Type() == "curating" { + if curating, ok := i.(*acl.Curating); ok { + return curating + } + } + } + return nil +} + +// Unused but may be needed for debugging +var _ = log.T +var _ = hex.EncodeToString diff --git a/cmd/orly-db-badger/main.go b/cmd/orly-db-badger/main.go new file mode 100644 index 0000000..9a2fe39 --- /dev/null +++ b/cmd/orly-db-badger/main.go @@ -0,0 +1,122 @@ +// orly-db-badger is a standalone gRPC database server using the Badger backend. +package main + +import ( + "context" + "os" + "path/filepath" + "time" + + "go-simpler.org/env" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/database" + "next.orly.dev/pkg/database/server" +) + +// Config holds the database server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_DB_LISTEN" default:"127.0.0.1:50051" usage:"gRPC server listen address"` + + // DataDir is the database data directory + DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_DB_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Badger configuration + BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"1024" usage:"block cache size in MB"` + IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"512" usage:"index cache size in MB"` + ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level (1-19)"` + + // Query cache configuration + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"256" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + + // Serial cache configuration + SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"` + SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"` + + // gRPC server configuration + StreamBatchSize int `env:"ORLY_DB_STREAM_BATCH_SIZE" default:"100" usage:"events per stream batch"` +} + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-db-badger starting with log level: %s", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Create database configuration + dbCfg := &database.DatabaseConfig{ + DataDir: cfg.DataDir, + LogLevel: cfg.LogLevel, + BlockCacheMB: cfg.BlockCacheMB, + IndexCacheMB: cfg.IndexCacheMB, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + SerialCachePubkeys: cfg.SerialCachePubkeys, + SerialCacheEventIds: cfg.SerialCacheEventIds, + ZSTDLevel: cfg.ZSTDLevel, + } + + // Initialize Badger database + log.I.F("initializing Badger database at %s", cfg.DataDir) + db, err := database.NewWithConfig(ctx, cancel, dbCfg) + if chk.E(err) { + log.E.F("failed to initialize database: %v", err) + os.Exit(1) + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create and start gRPC server + serverCfg := &server.Config{ + Listen: cfg.Listen, + LogLevel: cfg.LogLevel, + StreamBatchSize: cfg.StreamBatchSize, + } + + srv := server.New(db, serverCfg) + if err := srv.ListenAndServe(ctx, cancel); err != nil { + log.E.F("gRPC server error: %v", err) + } +} + +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + // Set default data directory if not specified + if cfg.DataDir == "" { + home, err := os.UserHomeDir() + if chk.E(err) { + log.E.F("failed to get home directory: %v", err) + os.Exit(1) + } + cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY") + } + + // Ensure data directory exists + if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) { + log.E.F("failed to create data directory %s: %v", cfg.DataDir, err) + os.Exit(1) + } + + return cfg +} diff --git a/cmd/orly-db-neo4j/main.go b/cmd/orly-db-neo4j/main.go new file mode 100644 index 0000000..3887104 --- /dev/null +++ b/cmd/orly-db-neo4j/main.go @@ -0,0 +1,108 @@ +// orly-db-neo4j is a standalone gRPC database server using the Neo4j backend. +package main + +import ( + "context" + "os" + "time" + + "go-simpler.org/env" + "lol.mleku.dev" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/database" + "next.orly.dev/pkg/database/server" + + // Import neo4j to register the factory + _ "next.orly.dev/pkg/neo4j" +) + +// Config holds the database server configuration. +type Config struct { + // Listen is the gRPC server listen address + Listen string `env:"ORLY_DB_LISTEN" default:"127.0.0.1:50051" usage:"gRPC server listen address"` + + // LogLevel is the logging level + LogLevel string `env:"ORLY_DB_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` + + // Neo4j configuration + Neo4jURI string `env:"ORLY_NEO4J_URI" default:"bolt://localhost:7687" usage:"Neo4j connection URI"` + Neo4jUser string `env:"ORLY_NEO4J_USER" default:"neo4j" usage:"Neo4j username"` + Neo4jPassword string `env:"ORLY_NEO4J_PASSWORD" usage:"Neo4j password"` + + // Neo4j driver tuning + Neo4jMaxConnPoolSize int `env:"ORLY_NEO4J_MAX_CONN_POOL" default:"25" usage:"max connection pool size"` + Neo4jFetchSize int `env:"ORLY_NEO4J_FETCH_SIZE" default:"1000" usage:"max records per fetch batch"` + Neo4jMaxTxRetrySeconds int `env:"ORLY_NEO4J_MAX_TX_RETRY_SEC" default:"30" usage:"max transaction retry time"` + Neo4jQueryResultLimit int `env:"ORLY_NEO4J_QUERY_RESULT_LIMIT" default:"10000" usage:"max results per query (0=unlimited)"` + + // Query cache configuration (for the gRPC server) + QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"256" usage:"query cache size in MB"` + QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` + QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` + + // gRPC server configuration + StreamBatchSize int `env:"ORLY_DB_STREAM_BATCH_SIZE" default:"100" usage:"events per stream batch"` +} + +func main() { + cfg := loadConfig() + + // Set log level + lol.SetLogLevel(cfg.LogLevel) + log.I.F("orly-db-neo4j starting with log level: %s", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Create database configuration + dbCfg := &database.DatabaseConfig{ + LogLevel: cfg.LogLevel, + Neo4jURI: cfg.Neo4jURI, + Neo4jUser: cfg.Neo4jUser, + Neo4jPassword: cfg.Neo4jPassword, + Neo4jMaxConnPoolSize: cfg.Neo4jMaxConnPoolSize, + Neo4jFetchSize: cfg.Neo4jFetchSize, + Neo4jMaxTxRetrySeconds: cfg.Neo4jMaxTxRetrySeconds, + Neo4jQueryResultLimit: cfg.Neo4jQueryResultLimit, + QueryCacheSizeMB: cfg.QueryCacheSizeMB, + QueryCacheMaxAge: cfg.QueryCacheMaxAge, + QueryCacheDisabled: cfg.QueryCacheDisabled, + } + + // Initialize Neo4j database via factory + log.I.F("connecting to Neo4j at %s", cfg.Neo4jURI) + db, err := database.NewDatabaseWithConfig(ctx, cancel, "neo4j", dbCfg) + if chk.E(err) { + log.E.F("failed to initialize Neo4j database: %v", err) + os.Exit(1) + } + + // Wait for database to be ready + log.I.F("waiting for database to be ready...") + <-db.Ready() + log.I.F("database ready") + + // Create and start gRPC server + serverCfg := &server.Config{ + Listen: cfg.Listen, + LogLevel: cfg.LogLevel, + StreamBatchSize: cfg.StreamBatchSize, + } + + srv := server.New(db, serverCfg) + if err := srv.ListenAndServe(ctx, cancel); err != nil { + log.E.F("gRPC server error: %v", err) + } +} + +func loadConfig() *Config { + cfg := &Config{} + if err := env.Load(cfg, nil); chk.E(err) { + log.E.F("failed to load config: %v", err) + os.Exit(1) + } + + return cfg +} diff --git a/cmd/orly-launcher/config.go b/cmd/orly-launcher/config.go index 49f005e..9e0e843 100644 --- a/cmd/orly-launcher/config.go +++ b/cmd/orly-launcher/config.go @@ -10,37 +10,71 @@ import ( // Config holds the launcher configuration. type Config struct { - // DBBinary is the path to the orly-db binary + // DBBackend is the database backend: badger or neo4j + DBBackend string + + // DBBinary is the path to the database server binary (computed from DBBackend if not set) DBBinary string // RelayBinary is the path to the orly binary RelayBinary string + // ACLBinary is the path to the ACL server binary (computed from ACLMode if not set) + ACLBinary string + // DBListen is the address the database server listens on DBListen string + // ACLListen is the address the ACL server listens on + ACLListen string + + // ACLEnabled controls whether to run the ACL server as a separate process + // When false, the relay runs in open mode (no ACL restrictions) + ACLEnabled bool + + // ACLMode is the ACL mode: follows, managed, curation + // Determines which ACL binary to use when ACLEnabled is true + ACLMode string + // DBReadyTimeout is how long to wait for the database to be ready DBReadyTimeout time.Duration + // ACLReadyTimeout is how long to wait for the ACL server to be ready + ACLReadyTimeout time.Duration + // StopTimeout is how long to wait for processes to stop gracefully StopTimeout time.Duration // DataDir is the data directory to pass to orly-db DataDir string - // LogLevel is the log level to use for both processes + // LogLevel is the log level to use for all processes LogLevel string } func loadConfig() (*Config, error) { + // Get backend and mode first to compute default binary names + dbBackend := getEnvOrDefault("ORLY_LAUNCHER_DB_BACKEND", "badger") + aclMode := getEnvOrDefault("ORLY_ACL_MODE", "follows") + + // Compute default binary names based on backend/mode + defaultDBBinary := "orly-db-" + dbBackend + defaultACLBinary := "orly-acl-" + aclMode + cfg := &Config{ - DBBinary: getEnvOrDefault("ORLY_LAUNCHER_DB_BINARY", "orly-db"), - RelayBinary: getEnvOrDefault("ORLY_LAUNCHER_RELAY_BINARY", "orly"), - DBListen: getEnvOrDefault("ORLY_LAUNCHER_DB_LISTEN", "127.0.0.1:50051"), - DBReadyTimeout: parseDuration("ORLY_LAUNCHER_DB_READY_TIMEOUT", 30*time.Second), - StopTimeout: parseDuration("ORLY_LAUNCHER_STOP_TIMEOUT", 30*time.Second), // Increased for DB flush - DataDir: getEnvOrDefault("ORLY_DATA_DIR", filepath.Join(xdg.DataHome, "ORLY")), - LogLevel: getEnvOrDefault("ORLY_LOG_LEVEL", "info"), + DBBackend: dbBackend, + DBBinary: getEnvOrDefault("ORLY_LAUNCHER_DB_BINARY", defaultDBBinary), + RelayBinary: getEnvOrDefault("ORLY_LAUNCHER_RELAY_BINARY", "orly"), + ACLBinary: getEnvOrDefault("ORLY_LAUNCHER_ACL_BINARY", defaultACLBinary), + DBListen: getEnvOrDefault("ORLY_LAUNCHER_DB_LISTEN", "127.0.0.1:50051"), + ACLListen: getEnvOrDefault("ORLY_LAUNCHER_ACL_LISTEN", "127.0.0.1:50052"), + ACLEnabled: getEnvOrDefault("ORLY_LAUNCHER_ACL_ENABLED", "false") == "true", + ACLMode: aclMode, + DBReadyTimeout: parseDuration("ORLY_LAUNCHER_DB_READY_TIMEOUT", 30*time.Second), + ACLReadyTimeout: parseDuration("ORLY_LAUNCHER_ACL_READY_TIMEOUT", 30*time.Second), + StopTimeout: parseDuration("ORLY_LAUNCHER_STOP_TIMEOUT", 30*time.Second), // Increased for DB flush + DataDir: getEnvOrDefault("ORLY_DATA_DIR", filepath.Join(xdg.DataHome, "ORLY")), + LogLevel: getEnvOrDefault("ORLY_LOG_LEVEL", "info"), } return cfg, nil diff --git a/cmd/orly-launcher/supervisor.go b/cmd/orly-launcher/supervisor.go index 60d8fe4..80744dc 100644 --- a/cmd/orly-launcher/supervisor.go +++ b/cmd/orly-launcher/supervisor.go @@ -14,13 +14,14 @@ import ( "lol.mleku.dev/log" ) -// Supervisor manages the database and relay processes. +// Supervisor manages the database, ACL, and relay processes. type Supervisor struct { cfg *Config ctx context.Context cancel context.CancelFunc dbProc *Process + aclProc *Process relayProc *Process wg sync.WaitGroup @@ -46,7 +47,7 @@ func NewSupervisor(ctx context.Context, cancel context.CancelFunc, cfg *Config) } } -// Start starts the database and relay processes. +// Start starts the database, optional ACL server, and relay processes. func (s *Supervisor) Start() error { // 1. Start database server if err := s.startDB(); err != nil { @@ -61,15 +62,42 @@ func (s *Supervisor) Start() error { log.I.F("database is ready") - // 3. Start relay with gRPC backend + // 3. Start ACL server if enabled + if s.cfg.ACLEnabled { + if err := s.startACL(); err != nil { + s.stopDB() + return fmt.Errorf("failed to start ACL server: %w", err) + } + + // Wait for ACL to be ready + if err := s.waitForACLReady(s.cfg.ACLReadyTimeout); err != nil { + s.stopACL() + s.stopDB() + return fmt.Errorf("ACL server not ready: %w", err) + } + + log.I.F("ACL server is ready") + } + + // 4. Start relay with gRPC backend(s) if err := s.startRelay(); err != nil { + if s.cfg.ACLEnabled { + s.stopACL() + } s.stopDB() return fmt.Errorf("failed to start relay: %w", err) } - // 4. Start monitoring goroutines - s.wg.Add(2) + // 5. Start monitoring goroutines + monitorCount := 2 + if s.cfg.ACLEnabled { + monitorCount = 3 + } + s.wg.Add(monitorCount) go s.monitorProcess(s.dbProc, "db", s.startDB) + if s.cfg.ACLEnabled { + go s.monitorProcess(s.aclProc, "acl", s.startACL) + } go s.monitorProcess(s.relayProc, "relay", s.startRelay) return nil @@ -85,10 +113,16 @@ func (s *Supervisor) Stop() error { s.closed = true s.mu.Unlock() - // Stop relay first (it depends on DB) + // Stop relay first (it depends on ACL and DB) log.I.F("stopping relay...") s.stopProcess(s.relayProc, 5*time.Second) + // Stop ACL if enabled (it depends on DB) + if s.cfg.ACLEnabled && s.aclProc != nil { + log.I.F("stopping ACL server...") + s.stopProcess(s.aclProc, 5*time.Second) + } + // Stop DB with longer timeout for flush log.I.F("stopping database...") s.stopProcess(s.dbProc, s.cfg.StopTimeout) @@ -135,6 +169,72 @@ func (s *Supervisor) startDB() error { return nil } +func (s *Supervisor) startACL() error { + s.mu.Lock() + defer s.mu.Unlock() + + // Build environment for ACL process + env := os.Environ() + env = append(env, fmt.Sprintf("ORLY_ACL_LISTEN=%s", s.cfg.ACLListen)) + env = append(env, "ORLY_ACL_DB_TYPE=grpc") + env = append(env, fmt.Sprintf("ORLY_ACL_GRPC_DB_SERVER=%s", s.cfg.DBListen)) + env = append(env, fmt.Sprintf("ORLY_ACL_MODE=%s", s.cfg.ACLMode)) + env = append(env, fmt.Sprintf("ORLY_ACL_LOG_LEVEL=%s", s.cfg.LogLevel)) + + cmd := exec.CommandContext(s.ctx, s.cfg.ACLBinary) + cmd.Env = env + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Start(); chk.E(err) { + return err + } + + exited := make(chan struct{}) + s.aclProc = &Process{ + name: "orly-acl", + cmd: cmd, + exited: exited, + } + + // Start a goroutine to wait for the process and close the exited channel + go func() { + cmd.Wait() + close(exited) + }() + + log.I.F("started ACL server (pid %d)", cmd.Process.Pid) + return nil +} + +func (s *Supervisor) waitForACLReady(timeout time.Duration) error { + deadline := time.Now().Add(timeout) + ticker := time.NewTicker(250 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-s.ctx.Done(): + return s.ctx.Err() + case <-ticker.C: + if time.Now().After(deadline) { + return fmt.Errorf("timeout waiting for ACL server") + } + + // Try to connect to the gRPC port + conn, err := net.DialTimeout("tcp", s.cfg.ACLListen, time.Second) + if err == nil { + conn.Close() + return nil // ACL server is accepting connections + } + } + } +} + +func (s *Supervisor) stopACL() { + s.stopProcess(s.aclProc, 5*time.Second) +} + func (s *Supervisor) startRelay() error { s.mu.Lock() defer s.mu.Unlock() @@ -145,6 +245,18 @@ func (s *Supervisor) startRelay() error { env = append(env, fmt.Sprintf("ORLY_GRPC_SERVER=%s", s.cfg.DBListen)) env = append(env, fmt.Sprintf("ORLY_LOG_LEVEL=%s", s.cfg.LogLevel)) + // If ACL is enabled, configure relay to use gRPC ACL + // Otherwise, run in open mode (no ACL restrictions) + if s.cfg.ACLEnabled { + env = append(env, "ORLY_ACL_TYPE=grpc") + env = append(env, fmt.Sprintf("ORLY_GRPC_ACL_SERVER=%s", s.cfg.ACLListen)) + env = append(env, fmt.Sprintf("ORLY_ACL_MODE=%s", s.cfg.ACLMode)) + } else { + // Open relay - no ACL restrictions + env = append(env, "ORLY_ACL_TYPE=local") + env = append(env, "ORLY_ACL_MODE=none") + } + cmd := exec.CommandContext(s.ctx, s.cfg.RelayBinary) cmd.Env = env cmd.Stdout = os.Stdout @@ -299,9 +411,12 @@ func (s *Supervisor) monitorProcess(p *Process, procType string, restart func() } else { // Update p to point to the new process s.mu.Lock() - if procType == "db" { + switch procType { + case "db": p = s.dbProc - } else { + case "acl": + p = s.aclProc + default: p = s.relayProc } s.mu.Unlock() diff --git a/main.go b/main.go index 593fc6c..416aad2 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,7 @@ import ( "next.orly.dev/app/branding" "next.orly.dev/app/config" "next.orly.dev/pkg/acl" + aclgrpc "next.orly.dev/pkg/acl/grpc" "git.mleku.dev/mleku/nostr/crypto/keys" "git.mleku.dev/mleku/nostr/encoders/bech32encoding" "next.orly.dev/pkg/database" @@ -580,11 +581,38 @@ func main() { os.Exit(1) } log.I.F("%s database initialized successfully", cfg.DBType) - acl.Registry.SetMode(cfg.ACLMode) - if err = acl.Registry.Configure(cfg, db, ctx); chk.E(err) { - os.Exit(1) + + // Initialize ACL - either remote gRPC or in-process + aclType, aclServerAddr, aclConnTimeout := cfg.GetGRPCACLConfigValues() + if aclType == "grpc" { + // Use remote ACL server via gRPC + log.I.F("connecting to gRPC ACL server at %s", aclServerAddr) + aclClient, aclErr := aclgrpc.New(ctx, &aclgrpc.ClientConfig{ + ServerAddress: aclServerAddr, + ConnectTimeout: aclConnTimeout, + }) + if chk.E(aclErr) { + log.E.F("failed to connect to gRPC ACL server: %v", aclErr) + os.Exit(1) + } + // Wait for ACL server to be ready + select { + case <-aclClient.Ready(): + log.I.F("gRPC ACL client connected, mode: %s", aclClient.Type()) + case <-time.After(30 * time.Second): + log.E.F("timeout waiting for gRPC ACL server") + os.Exit(1) + } + // Register and activate the gRPC client as the ACL backend + acl.Registry.RegisterAndActivate(aclClient) + } else { + // Use in-process ACL (existing behavior) + acl.Registry.SetMode(cfg.ACLMode) + if err = acl.Registry.Configure(cfg, db, ctx); chk.E(err) { + os.Exit(1) + } + acl.Registry.Syncer() } - acl.Registry.Syncer() // Create rate limiter if enabled var limiter *ratelimit.Limiter diff --git a/orly.service b/orly.service new file mode 100644 index 0000000..4d46688 --- /dev/null +++ b/orly.service @@ -0,0 +1,66 @@ +[Unit] +Description=ORLY Nostr Relay (Split IPC Mode) +After=network.target + +[Service] +Type=simple +User=mleku +Group=mleku +WorkingDirectory=/home/mleku/src/next.orly.dev + +# Use orly-launcher which manages orly-db-badger, orly-acl-follows, and the relay +ExecStart=/home/mleku/.local/bin/orly-launcher + +# Launcher config - paths to split binaries +Environment=ORLY_LAUNCHER_DB_BACKEND=badger +Environment=ORLY_LAUNCHER_DB_BINARY=/home/mleku/.local/bin/orly-db-badger +Environment=ORLY_LAUNCHER_ACL_BINARY=/home/mleku/.local/bin/orly-acl-follows +Environment=ORLY_LAUNCHER_RELAY_BINARY=/home/mleku/.local/bin/next.orly.dev +Environment=ORLY_LAUNCHER_DB_LISTEN=127.0.0.1:50051 +Environment=ORLY_LAUNCHER_ACL_LISTEN=127.0.0.1:50052 +Environment=ORLY_LAUNCHER_ACL_ENABLED=true +Environment=ORLY_ACL_MODE=follows + +# gRPC client settings (for relay to connect to db and acl) +Environment=ORLY_DB_TYPE=grpc +Environment=ORLY_GRPC_SERVER=127.0.0.1:50051 +Environment=ORLY_ACL_TYPE=grpc +Environment=ORLY_GRPC_ACL_SERVER=127.0.0.1:50052 + +# Relay settings +Environment=ORLY_PORT=3334 +Environment=ORLY_LISTEN=127.0.0.1 +Environment=ORLY_LOG_LEVEL=info +Environment=ORLY_ADMINS=npub1fjqqy4a93z5zsjwsfxqhc2764kvykfdyttvldkkkdera8dr78vhsmmleku +Environment=ORLY_OWNERS=npub1fjqqy4a93z5zsjwsfxqhc2764kvykfdyttvldkkkdera8dr78vhsmmleku +Environment=ORLY_AUTH_REQUIRED=false +Environment=ORLY_AUTH_TO_WRITE=false +Environment=ORLY_NIP46_BYPASS_AUTH=true +Environment=ORLY_FOLLOWS_THROTTLE=true +Environment=ORLY_BLOSSOM_RATE_LIMIT=true +Environment=ORLY_BLOSSOM_DAILY_LIMIT_MB=10 + +# Memory settings for database server (orly-db-badger) +Environment=ORLY_DB_BLOCK_CACHE_MB=256 +Environment=ORLY_DB_INDEX_CACHE_MB=128 +Environment=ORLY_QUERY_CACHE_DISABLED=false +Environment=ORLY_QUERY_CACHE_SIZE_MB=64 +Environment=ORLY_SERIAL_CACHE_PUBKEYS=100000 +Environment=ORLY_SERIAL_CACHE_EVENT_IDS=500000 +Environment=ORLY_GC_ENABLED=false + +# Rate limiting for relay process +Environment=ORLY_RATE_LIMIT_TARGET_MB=2000 + +# Connection and query limits +Environment=ORLY_MAX_CONN_PER_IP=5 +Environment=ORLY_QUERY_RESULT_LIMIT=256 + +# Enable pprof HTTP endpoint for debugging +Environment=ORLY_PPROF_HTTP=true + +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/pkg/acl/acl.go b/pkg/acl/acl.go index f685e0d..af4f48f 100644 --- a/pkg/acl/acl.go +++ b/pkg/acl/acl.go @@ -27,6 +27,13 @@ func (s *S) Register(i acliface.I) { (*s).ACL = append((*s).ACL, i) } +// RegisterAndActivate registers an ACL implementation and sets it as the active one. +// This is used for gRPC clients where the mode is determined by the remote server. +func (s *S) RegisterAndActivate(i acliface.I) { + s.ACL = []acliface.I{i} + s.SetMode(i.Type()) +} + func (s *S) Configure(cfg ...any) (err error) { for _, i := range s.ACL { if i.Type() == s.Active.Load() { diff --git a/pkg/acl/grpc/client.go b/pkg/acl/grpc/client.go new file mode 100644 index 0000000..30320c2 --- /dev/null +++ b/pkg/acl/grpc/client.go @@ -0,0 +1,384 @@ +// Package grpc provides a gRPC client that implements the acl.I interface. +// This allows the relay to use a remote ACL server via gRPC. +package grpc + +import ( + "context" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "git.mleku.dev/mleku/nostr/encoders/event" + acliface "next.orly.dev/pkg/interfaces/acl" + orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1" + orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1" +) + +// Client implements the acl.I interface via gRPC. +type Client struct { + conn *grpc.ClientConn + client orlyaclv1.ACLServiceClient + ready chan struct{} + mode string +} + +// Verify Client implements acl.I at compile time. +var _ acliface.I = (*Client)(nil) + +// Verify Client implements acl.PolicyChecker at compile time. +var _ acliface.PolicyChecker = (*Client)(nil) + +// ClientConfig holds configuration for the gRPC ACL client. +type ClientConfig struct { + ServerAddress string + ConnectTimeout time.Duration +} + +// New creates a new gRPC ACL client. +func New(ctx context.Context, cfg *ClientConfig) (*Client, error) { + timeout := cfg.ConnectTimeout + if timeout == 0 { + timeout = 10 * time.Second + } + + dialCtx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + conn, err := grpc.DialContext(dialCtx, cfg.ServerAddress, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions( + grpc.MaxCallRecvMsgSize(16<<20), // 16MB + grpc.MaxCallSendMsgSize(16<<20), // 16MB + ), + ) + if err != nil { + return nil, err + } + + c := &Client{ + conn: conn, + client: orlyaclv1.NewACLServiceClient(conn), + ready: make(chan struct{}), + } + + // Check if server is ready and get mode + go c.waitForReady(ctx) + + return c, nil +} + +func (c *Client) waitForReady(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + default: + resp, err := c.client.Ready(ctx, &orlyaclv1.Empty{}) + if err == nil && resp.Ready { + // Get mode from server + modeResp, err := c.client.GetMode(ctx, &orlyaclv1.Empty{}) + if err == nil { + c.mode = modeResp.Mode + } + close(c.ready) + log.I.F("gRPC ACL client connected and ready, mode: %s", c.mode) + return + } + time.Sleep(100 * time.Millisecond) + } + } +} + +// Close closes the gRPC connection. +func (c *Client) Close() error { + if c.conn != nil { + return c.conn.Close() + } + return nil +} + +// Ready returns a channel that closes when the client is ready. +func (c *Client) Ready() <-chan struct{} { + return c.ready +} + +// === acl.I Interface Implementation === + +func (c *Client) Configure(cfg ...any) error { + // Configuration is done on the server side + // The client just passes through to the server + return nil +} + +func (c *Client) GetAccessLevel(pub []byte, address string) string { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.GetAccessLevel(ctx, &orlyaclv1.AccessLevelRequest{ + Pubkey: pub, + Address: address, + }) + if chk.E(err) { + return "none" + } + return resp.Level +} + +func (c *Client) GetACLInfo() (name, description, documentation string) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.GetACLInfo(ctx, &orlyaclv1.Empty{}) + if chk.E(err) { + return "", "", "" + } + return resp.Name, resp.Description, resp.Documentation +} + +func (c *Client) Syncer() { + // The syncer runs on the ACL server, not the client + // This is a no-op for the gRPC client +} + +func (c *Client) Type() string { + return c.mode +} + +// === acl.PolicyChecker Interface Implementation === + +func (c *Client) CheckPolicy(ev *event.E) (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.CheckPolicy(ctx, &orlyaclv1.PolicyCheckRequest{ + Event: orlydbv1.EventToProto(ev), + }) + if err != nil { + return false, err + } + if resp.Error != "" { + return resp.Allowed, &policyError{msg: resp.Error} + } + return resp.Allowed, nil +} + +// policyError is a simple error type for policy check failures +type policyError struct { + msg string +} + +func (e *policyError) Error() string { + return e.msg +} + +// === Follows ACL Methods === + +// GetThrottleDelay returns the progressive throttle delay for a pubkey. +func (c *Client) GetThrottleDelay(pubkey []byte, ip string) time.Duration { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.GetThrottleDelay(ctx, &orlyaclv1.ThrottleDelayRequest{ + Pubkey: pubkey, + Ip: ip, + }) + if chk.E(err) { + return 0 + } + return time.Duration(resp.DelayMs) * time.Millisecond +} + +// AddFollow adds a pubkey to the followed list. +func (c *Client) AddFollow(pubkey []byte) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.AddFollow(ctx, &orlyaclv1.AddFollowRequest{ + Pubkey: pubkey, + }) + return err +} + +// GetFollowedPubkeys returns all followed pubkeys. +func (c *Client) GetFollowedPubkeys() [][]byte { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + resp, err := c.client.GetFollowedPubkeys(ctx, &orlyaclv1.Empty{}) + if chk.E(err) { + return nil + } + return resp.Pubkeys +} + +// GetAdminRelays returns the admin relay URLs. +func (c *Client) GetAdminRelays() []string { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.GetAdminRelays(ctx, &orlyaclv1.Empty{}) + if chk.E(err) { + return nil + } + return resp.Urls +} + +// === Managed ACL Methods === + +// BanPubkey adds a pubkey to the ban list. +func (c *Client) BanPubkey(pubkey, reason string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.BanPubkey(ctx, &orlyaclv1.BanPubkeyRequest{ + Pubkey: pubkey, + Reason: reason, + }) + return err +} + +// UnbanPubkey removes a pubkey from the ban list. +func (c *Client) UnbanPubkey(pubkey string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.UnbanPubkey(ctx, &orlyaclv1.PubkeyRequest{ + Pubkey: pubkey, + }) + return err +} + +// AllowPubkey adds a pubkey to the allow list. +func (c *Client) AllowPubkey(pubkey, reason string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.AllowPubkey(ctx, &orlyaclv1.AllowPubkeyRequest{ + Pubkey: pubkey, + Reason: reason, + }) + return err +} + +// DisallowPubkey removes a pubkey from the allow list. +func (c *Client) DisallowPubkey(pubkey string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.DisallowPubkey(ctx, &orlyaclv1.PubkeyRequest{ + Pubkey: pubkey, + }) + return err +} + +// BlockIP adds an IP to the block list. +func (c *Client) BlockIP(ip, reason string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.BlockIP(ctx, &orlyaclv1.BlockIPRequest{ + Ip: ip, + Reason: reason, + }) + return err +} + +// UnblockIP removes an IP from the block list. +func (c *Client) UnblockIP(ip string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.UnblockIP(ctx, &orlyaclv1.IPRequest{ + Ip: ip, + }) + return err +} + +// UpdatePeerAdmins updates the peer relay identity pubkeys. +func (c *Client) UpdatePeerAdmins(peerPubkeys [][]byte) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.UpdatePeerAdmins(ctx, &orlyaclv1.UpdatePeerAdminsRequest{ + PeerPubkeys: peerPubkeys, + }) + return err +} + +// === Curating ACL Methods === + +// TrustPubkey adds a pubkey to the trusted list. +func (c *Client) TrustPubkey(pubkey, note string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.TrustPubkey(ctx, &orlyaclv1.TrustPubkeyRequest{ + Pubkey: pubkey, + Note: note, + }) + return err +} + +// UntrustPubkey removes a pubkey from the trusted list. +func (c *Client) UntrustPubkey(pubkey string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.UntrustPubkey(ctx, &orlyaclv1.PubkeyRequest{ + Pubkey: pubkey, + }) + return err +} + +// BlacklistPubkey adds a pubkey to the blacklist. +func (c *Client) BlacklistPubkey(pubkey, reason string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.BlacklistPubkey(ctx, &orlyaclv1.BlacklistPubkeyRequest{ + Pubkey: pubkey, + Reason: reason, + }) + return err +} + +// UnblacklistPubkey removes a pubkey from the blacklist. +func (c *Client) UnblacklistPubkey(pubkey string) error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err := c.client.UnblacklistPubkey(ctx, &orlyaclv1.PubkeyRequest{ + Pubkey: pubkey, + }) + return err +} + +// RateLimitCheck checks if a pubkey/IP can publish. +func (c *Client) RateLimitCheck(pubkey, ip string) (allowed bool, message string, err error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.RateLimitCheck(ctx, &orlyaclv1.RateLimitCheckRequest{ + Pubkey: pubkey, + Ip: ip, + }) + if err != nil { + return false, "", err + } + return resp.Allowed, resp.Message, nil +} + +// IsCuratingConfigured checks if curating mode is configured. +func (c *Client) IsCuratingConfigured() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + resp, err := c.client.IsCuratingConfigured(ctx, &orlyaclv1.Empty{}) + if err != nil { + return false, err + } + return resp.Value, nil +} diff --git a/pkg/acl/server/config.go b/pkg/acl/server/config.go new file mode 100644 index 0000000..fdf24a9 --- /dev/null +++ b/pkg/acl/server/config.go @@ -0,0 +1,32 @@ +// Package server provides a shared gRPC ACL server implementation. +package server + +import "time" + +// Config holds configuration for the ACL gRPC server. +type Config struct { + // Listen is the gRPC server listen address + Listen string + + // ACLMode is the active ACL mode (none, follows, managed, curating) + ACLMode string + + // LogLevel is the logging level + LogLevel string + + // Owner and admin lists + Owners []string + Admins []string + + // Bootstrap relays for follow list syncing + BootstrapRelays []string + + // Relay addresses (self) + RelayAddresses []string + + // Follows ACL configuration + FollowListFrequency time.Duration + FollowsThrottleEnabled bool + FollowsThrottlePerEvent time.Duration + FollowsThrottleMaxDelay time.Duration +} diff --git a/pkg/acl/server/server.go b/pkg/acl/server/server.go new file mode 100644 index 0000000..0e6001c --- /dev/null +++ b/pkg/acl/server/server.go @@ -0,0 +1,144 @@ +package server + +import ( + "context" + "net" + "os" + "os/signal" + "syscall" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/app/config" + "next.orly.dev/pkg/acl" + "next.orly.dev/pkg/database" + orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1" +) + +// Server wraps a gRPC ACL server. +type Server struct { + grpcServer *grpc.Server + db database.Database + cfg *Config + listener net.Listener + ownsDB bool // Whether we own the database and should close it +} + +// New creates a new ACL gRPC server. +func New(db database.Database, cfg *Config, ownsDB bool) *Server { + // Create gRPC server + grpcServer := grpc.NewServer( + grpc.MaxRecvMsgSize(16<<20), // 16MB + grpc.MaxSendMsgSize(16<<20), // 16MB + ) + + // Register ACL service + service := NewACLService(cfg, db) + orlyaclv1.RegisterACLServiceServer(grpcServer, service) + + // Register reflection for debugging with grpcurl + reflection.Register(grpcServer) + + return &Server{ + grpcServer: grpcServer, + db: db, + cfg: cfg, + ownsDB: ownsDB, + } +} + +// ConfigureACL sets up the ACL mode and configures the registry. +func (s *Server) ConfigureACL(ctx context.Context) error { + // Create app config for ACL configuration + appCfg := &config.C{ + Owners: s.cfg.Owners, + Admins: s.cfg.Admins, + BootstrapRelays: s.cfg.BootstrapRelays, + RelayAddresses: s.cfg.RelayAddresses, + FollowListFrequency: s.cfg.FollowListFrequency, + FollowsThrottleEnabled: s.cfg.FollowsThrottleEnabled, + FollowsThrottlePerEvent: s.cfg.FollowsThrottlePerEvent, + FollowsThrottleMaxDelay: s.cfg.FollowsThrottleMaxDelay, + } + + // Set ACL mode and configure the registry + acl.Registry.SetMode(s.cfg.ACLMode) + if err := acl.Registry.Configure(appCfg, s.db, ctx); chk.E(err) { + return err + } + + // Start the syncer goroutine for background operations + acl.Registry.Syncer() + log.I.F("ACL syncer started for mode: %s", s.cfg.ACLMode) + + return nil +} + +// ListenAndServe starts the gRPC server. +func (s *Server) ListenAndServe(ctx context.Context, cancel context.CancelFunc) error { + // Start listening + lis, err := net.Listen("tcp", s.cfg.Listen) + if chk.E(err) { + return err + } + s.listener = lis + log.I.F("gRPC ACL server listening on %s", s.cfg.Listen) + + // Handle graceful shutdown + go s.handleShutdown(ctx, cancel) + + // Serve gRPC + return s.grpcServer.Serve(lis) +} + +func (s *Server) handleShutdown(ctx context.Context, cancel context.CancelFunc) { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT) + + select { + case sig := <-sigs: + log.I.F("received signal %v, shutting down...", sig) + case <-ctx.Done(): + log.I.F("context cancelled, shutting down...") + } + + // Cancel context to stop all operations + cancel() + + // Gracefully stop gRPC server with timeout + stopped := make(chan struct{}) + go func() { + s.grpcServer.GracefulStop() + close(stopped) + }() + + select { + case <-stopped: + log.I.F("gRPC server stopped gracefully") + case <-time.After(5 * time.Second): + log.W.F("gRPC graceful stop timed out, forcing stop") + s.grpcServer.Stop() + } + + // Sync and close database if we own it + if s.ownsDB { + log.I.F("syncing database...") + if err := s.db.Sync(); chk.E(err) { + log.W.F("failed to sync database: %v", err) + } + log.I.F("closing database...") + if err := s.db.Close(); chk.E(err) { + log.W.F("failed to close database: %v", err) + } + } + log.I.F("shutdown complete") +} + +// Stop stops the server. +func (s *Server) Stop() { + s.grpcServer.Stop() +} diff --git a/pkg/acl/server/service.go b/pkg/acl/server/service.go new file mode 100644 index 0000000..af9297e --- /dev/null +++ b/pkg/acl/server/service.go @@ -0,0 +1,788 @@ +package server + +import ( + "context" + "encoding/hex" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/acl" + "next.orly.dev/pkg/database" + orlyaclv1 "next.orly.dev/pkg/proto/orlyacl/v1" + orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1" +) + +// ACLService implements the orlyaclv1.ACLServiceServer interface. +type ACLService struct { + orlyaclv1.UnimplementedACLServiceServer + cfg *Config + db database.Database +} + +// NewACLService creates a new ACL service. +func NewACLService(cfg *Config, db database.Database) *ACLService { + return &ACLService{ + cfg: cfg, + db: db, + } +} + +// === Core ACL Methods === + +func (s *ACLService) GetAccessLevel(ctx context.Context, req *orlyaclv1.AccessLevelRequest) (*orlyaclv1.AccessLevelResponse, error) { + level := acl.Registry.GetAccessLevel(req.Pubkey, req.Address) + return &orlyaclv1.AccessLevelResponse{Level: level}, nil +} + +func (s *ACLService) CheckPolicy(ctx context.Context, req *orlyaclv1.PolicyCheckRequest) (*orlyaclv1.PolicyCheckResponse, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + allowed, err := acl.Registry.CheckPolicy(ev) + resp := &orlyaclv1.PolicyCheckResponse{Allowed: allowed} + if err != nil { + resp.Error = err.Error() + } + return resp, nil +} + +func (s *ACLService) GetACLInfo(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ACLInfoResponse, error) { + name, description, documentation := acl.Registry.GetACLInfo() + return &orlyaclv1.ACLInfoResponse{ + Name: name, + Description: description, + Documentation: documentation, + }, nil +} + +func (s *ACLService) GetMode(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ModeResponse, error) { + return &orlyaclv1.ModeResponse{Mode: acl.Registry.Type()}, nil +} + +func (s *ACLService) Ready(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ReadyResponse, error) { + // Check if database is ready + select { + case <-s.db.Ready(): + return &orlyaclv1.ReadyResponse{Ready: true}, nil + default: + return &orlyaclv1.ReadyResponse{Ready: false}, nil + } +} + +// === Follows ACL Methods === + +func (s *ACLService) GetThrottleDelay(ctx context.Context, req *orlyaclv1.ThrottleDelayRequest) (*orlyaclv1.ThrottleDelayResponse, error) { + // Get the active ACL and check if it's Follows + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + delay := follows.GetThrottleDelay(req.Pubkey, req.Ip) + return &orlyaclv1.ThrottleDelayResponse{DelayMs: delay.Milliseconds()}, nil + } + } + } + return &orlyaclv1.ThrottleDelayResponse{DelayMs: 0}, nil +} + +func (s *ACLService) AddFollow(ctx context.Context, req *orlyaclv1.AddFollowRequest) (*orlyaclv1.Empty, error) { + acl.Registry.AddFollow(req.Pubkey) + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) GetFollowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.FollowedPubkeysResponse, error) { + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + pubkeys := follows.GetFollowedPubkeys() + return &orlyaclv1.FollowedPubkeysResponse{Pubkeys: pubkeys}, nil + } + } + } + return &orlyaclv1.FollowedPubkeysResponse{}, nil +} + +func (s *ACLService) GetAdminRelays(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.AdminRelaysResponse, error) { + for _, i := range acl.Registry.ACL { + if i.Type() == "follows" { + if follows, ok := i.(*acl.Follows); ok { + urls := follows.AdminRelays() + return &orlyaclv1.AdminRelaysResponse{Urls: urls}, nil + } + } + } + return &orlyaclv1.AdminRelaysResponse{}, nil +} + +// === Managed ACL Methods === + +func (s *ACLService) BanPubkey(ctx context.Context, req *orlyaclv1.BanPubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBannedPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to ban pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnbanPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBannedPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unban pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBannedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedPubkeysResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + banned, err := managedACL.ListBannedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list banned pubkeys: %v", err) + } + resp := &orlyaclv1.ListBannedPubkeysResponse{} + for _, b := range banned { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BannedPubkey{ + Pubkey: b.Pubkey, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowPubkey(ctx context.Context, req *orlyaclv1.AllowPubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedPubkeysResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + allowed, err := managedACL.ListAllowedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed pubkeys: %v", err) + } + resp := &orlyaclv1.ListAllowedPubkeysResponse{} + for _, a := range allowed { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.AllowedPubkey{ + Pubkey: a.Pubkey, + Reason: a.Reason, + Added: a.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BanEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBannedEvent(req.EventId, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to ban event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnbanEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBannedEvent(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unban event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBannedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBannedEventsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + banned, err := managedACL.ListBannedEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list banned events: %v", err) + } + resp := &orlyaclv1.ListBannedEventsResponse{} + for _, b := range banned { + resp.Events = append(resp.Events, &orlyaclv1.BannedEvent{ + EventId: b.ID, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowEvent(ctx context.Context, req *orlyaclv1.BanEventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedEvent(req.EventId, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowEvent(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedEvent(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedEventsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + allowed, err := managedACL.ListAllowedEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed events: %v", err) + } + resp := &orlyaclv1.ListAllowedEventsResponse{} + for _, a := range allowed { + resp.Events = append(resp.Events, &orlyaclv1.AllowedEvent{ + EventId: a.ID, + Reason: a.Reason, + Added: a.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BlockIP(ctx context.Context, req *orlyaclv1.BlockIPRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveBlockedIP(req.Ip, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to block IP: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnblockIP(ctx context.Context, req *orlyaclv1.IPRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveBlockedIP(req.Ip); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unblock IP: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBlockedIPs(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlockedIPsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + blocked, err := managedACL.ListBlockedIPs() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list blocked IPs: %v", err) + } + resp := &orlyaclv1.ListBlockedIPsResponse{} + for _, b := range blocked { + resp.Ips = append(resp.Ips, &orlyaclv1.BlockedIP{ + Ip: b.IP, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) AllowKind(ctx context.Context, req *orlyaclv1.AllowKindRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.SaveAllowedKind(int(req.Kind)); err != nil { + return nil, status.Errorf(codes.Internal, "failed to allow kind: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) DisallowKind(ctx context.Context, req *orlyaclv1.KindRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + if err := managedACL.RemoveAllowedKind(int(req.Kind)); err != nil { + return nil, status.Errorf(codes.Internal, "failed to disallow kind: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListAllowedKinds(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListAllowedKindsResponse, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managedACL := managed.GetManagedACL() + if managedACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL database not available") + } + kinds, err := managedACL.ListAllowedKinds() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list allowed kinds: %v", err) + } + resp := &orlyaclv1.ListAllowedKindsResponse{} + for _, k := range kinds { + resp.Kinds = append(resp.Kinds, int32(k)) + } + return resp, nil +} + +func (s *ACLService) UpdatePeerAdmins(ctx context.Context, req *orlyaclv1.UpdatePeerAdminsRequest) (*orlyaclv1.Empty, error) { + managed := s.getManagedACL() + if managed == nil { + return nil, status.Errorf(codes.FailedPrecondition, "managed ACL not available") + } + managed.UpdatePeerAdmins(req.PeerPubkeys) + return &orlyaclv1.Empty{}, nil +} + +// === Curating ACL Methods === + +func (s *ACLService) TrustPubkey(ctx context.Context, req *orlyaclv1.TrustPubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.TrustPubkey(req.Pubkey, req.Note); err != nil { + return nil, status.Errorf(codes.Internal, "failed to trust pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UntrustPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.UntrustPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to untrust pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListTrustedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListTrustedPubkeysResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + trusted, err := curatingACL.ListTrustedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list trusted pubkeys: %v", err) + } + resp := &orlyaclv1.ListTrustedPubkeysResponse{} + for _, t := range trusted { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.TrustedPubkey{ + Pubkey: t.Pubkey, + Note: t.Note, + Added: t.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) BlacklistPubkey(ctx context.Context, req *orlyaclv1.BlacklistPubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.BlacklistPubkey(req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to blacklist pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnblacklistPubkey(ctx context.Context, req *orlyaclv1.PubkeyRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + if err := curating.UnblacklistPubkey(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unblacklist pubkey: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListBlacklistedPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListBlacklistedPubkeysResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + blacklisted, err := curatingACL.ListBlacklistedPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list blacklisted pubkeys: %v", err) + } + resp := &orlyaclv1.ListBlacklistedPubkeysResponse{} + for _, b := range blacklisted { + resp.Pubkeys = append(resp.Pubkeys, &orlyaclv1.BlacklistedPubkey{ + Pubkey: b.Pubkey, + Reason: b.Reason, + Added: b.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) MarkSpam(ctx context.Context, req *orlyaclv1.MarkSpamRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + if err := curatingACL.MarkEventAsSpam(req.EventId, req.Pubkey, req.Reason); err != nil { + return nil, status.Errorf(codes.Internal, "failed to mark spam: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) UnmarkSpam(ctx context.Context, req *orlyaclv1.EventRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + if err := curatingACL.UnmarkEventAsSpam(req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "failed to unmark spam: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) ListSpamEvents(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ListSpamEventsResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + spam, err := curatingACL.ListSpamEvents() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list spam events: %v", err) + } + resp := &orlyaclv1.ListSpamEventsResponse{} + for _, se := range spam { + resp.Events = append(resp.Events, &orlyaclv1.SpamEvent{ + EventId: se.EventID, + Pubkey: se.Pubkey, + Reason: se.Reason, + Added: se.Added.Unix(), + }) + } + return resp, nil +} + +func (s *ACLService) RateLimitCheck(ctx context.Context, req *orlyaclv1.RateLimitCheckRequest) (*orlyaclv1.RateLimitCheckResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + allowed, message, err := curating.RateLimitCheck(req.Pubkey, req.Ip) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to check rate limit: %v", err) + } + return &orlyaclv1.RateLimitCheckResponse{ + Allowed: allowed, + Message: message, + }, nil +} + +func (s *ACLService) ProcessConfigEvent(ctx context.Context, req *orlyaclv1.ConfigEventRequest) (*orlyaclv1.Empty, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + ev := orlydbv1.ProtoToEvent(req.Event) + if err := curating.ProcessConfigEvent(ev); err != nil { + return nil, status.Errorf(codes.Internal, "failed to process config event: %v", err) + } + return &orlyaclv1.Empty{}, nil +} + +func (s *ACLService) GetCuratingConfig(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.CuratingConfig, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + config, err := curating.GetConfig() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get config: %v", err) + } + resp := &orlyaclv1.CuratingConfig{ + ConfigEventId: config.ConfigEventID, + ConfigPubkey: config.ConfigPubkey, + ConfiguredAt: config.ConfiguredAt, + DailyLimit: int32(config.DailyLimit), + IpDailyLimit: int32(config.IPDailyLimit), + FirstBanHours: int32(config.FirstBanHours), + SecondBanHours: int32(config.SecondBanHours), + KindCategories: config.KindCategories, + AllowedRanges: config.AllowedRanges, + } + for _, k := range config.AllowedKinds { + resp.AllowedKinds = append(resp.AllowedKinds, int32(k)) + } + return resp, nil +} + +func (s *ACLService) IsCuratingConfigured(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.BoolResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return &orlyaclv1.BoolResponse{Value: false}, nil + } + configured, err := curating.IsConfigured() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to check if configured: %v", err) + } + return &orlyaclv1.BoolResponse{Value: configured}, nil +} + +func (s *ACLService) ListUnclassifiedUsers(ctx context.Context, req *orlyaclv1.PaginationRequest) (*orlyaclv1.ListUnclassifiedUsersResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + // The underlying ListUnclassifiedUsers only takes limit, not offset + // We'll request limit+offset and skip the first offset items + limit := int(req.Limit) + offset := int(req.Offset) + if limit == 0 { + limit = 100 // Default limit + } + users, err := curatingACL.ListUnclassifiedUsers(limit + offset) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list unclassified users: %v", err) + } + // Apply offset + if offset > 0 && len(users) > offset { + users = users[offset:] + } else if offset > 0 { + users = nil + } + // Apply limit + if limit > 0 && len(users) > limit { + users = users[:limit] + } + resp := &orlyaclv1.ListUnclassifiedUsersResponse{Total: int32(len(users))} + for _, u := range users { + resp.Users = append(resp.Users, &orlyaclv1.UnclassifiedUser{ + Pubkey: u.Pubkey, + EventCount: int32(u.EventCount), + FirstSeen: u.LastEvent.Format("2006-01-02T15:04:05Z"), + }) + } + return resp, nil +} + +func (s *ACLService) GetEventsForPubkey(ctx context.Context, req *orlyaclv1.GetEventsForPubkeyRequest) (*orlyaclv1.EventsForPubkeyResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + events, total, err := curatingACL.GetEventsForPubkey(req.Pubkey, int(req.Limit), int(req.Offset)) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get events for pubkey: %v", err) + } + resp := &orlyaclv1.EventsForPubkeyResponse{Total: int32(total)} + for _, ev := range events { + resp.Events = append(resp.Events, &orlyaclv1.EventSummary{ + Id: ev.ID, + Kind: uint32(ev.Kind), + Content: []byte(ev.Content), + CreatedAt: ev.CreatedAt, + }) + } + return resp, nil +} + +func (s *ACLService) DeleteEventsForPubkey(ctx context.Context, req *orlyaclv1.DeleteEventsForPubkeyRequest) (*orlyaclv1.DeleteCountResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + count, err := curatingACL.DeleteEventsForPubkey(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to delete events for pubkey: %v", err) + } + return &orlyaclv1.DeleteCountResponse{Count: int32(count)}, nil +} + +func (s *ACLService) ScanAllPubkeys(ctx context.Context, req *orlyaclv1.Empty) (*orlyaclv1.ScanResultResponse, error) { + curating := s.getCuratingACL() + if curating == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL not available") + } + curatingACL := curating.GetCuratingACL() + if curatingACL == nil { + return nil, status.Errorf(codes.FailedPrecondition, "curating ACL database not available") + } + result, err := curatingACL.ScanAllPubkeys() + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to scan all pubkeys: %v", err) + } + return &orlyaclv1.ScanResultResponse{ + TotalPubkeys: int32(result.TotalPubkeys), + TotalEvents: int32(result.TotalEvents), + }, nil +} + +// === Helper Methods === + +func (s *ACLService) getManagedACL() *acl.Managed { + for _, i := range acl.Registry.ACL { + if i.Type() == "managed" { + if managed, ok := i.(*acl.Managed); ok { + return managed + } + } + } + return nil +} + +func (s *ACLService) getCuratingACL() *acl.Curating { + for _, i := range acl.Registry.ACL { + if i.Type() == "curating" { + if curating, ok := i.(*acl.Curating); ok { + return curating + } + } + } + return nil +} + +// Unused but may be needed for debugging +var _ = log.T +var _ = hex.EncodeToString diff --git a/pkg/database/server/config.go b/pkg/database/server/config.go new file mode 100644 index 0000000..711f2cf --- /dev/null +++ b/pkg/database/server/config.go @@ -0,0 +1,33 @@ +// Package server provides a shared gRPC database server implementation. +package server + +import "time" + +// Config holds configuration for the database gRPC server. +type Config struct { + // Listen is the gRPC server listen address + Listen string + + // LogLevel is the logging level + LogLevel string + + // StreamBatchSize is the number of events per stream batch + StreamBatchSize int + + // MaxConcurrentQueries is the max concurrent queries + MaxConcurrentQueries int +} + +// DatabaseConfig holds Badger-specific configuration. +type DatabaseConfig struct { + DataDir string + LogLevel string + BlockCacheMB int + IndexCacheMB int + ZSTDLevel int + QueryCacheSizeMB int + QueryCacheMaxAge time.Duration + QueryCacheDisabled bool + SerialCachePubkeys int + SerialCacheEventIds int +} diff --git a/pkg/database/server/server.go b/pkg/database/server/server.go new file mode 100644 index 0000000..887b29e --- /dev/null +++ b/pkg/database/server/server.go @@ -0,0 +1,111 @@ +package server + +import ( + "context" + "net" + "os" + "os/signal" + "syscall" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/database" + orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1" +) + +// Server wraps a gRPC database server. +type Server struct { + grpcServer *grpc.Server + db database.Database + cfg *Config + listener net.Listener +} + +// New creates a new database gRPC server. +func New(db database.Database, cfg *Config) *Server { + // Create gRPC server with large message sizes for events + grpcServer := grpc.NewServer( + grpc.MaxRecvMsgSize(64<<20), // 64MB + grpc.MaxSendMsgSize(64<<20), // 64MB + ) + + // Register database service + service := NewDatabaseService(db, cfg) + orlydbv1.RegisterDatabaseServiceServer(grpcServer, service) + + // Register reflection for debugging with grpcurl + reflection.Register(grpcServer) + + return &Server{ + grpcServer: grpcServer, + db: db, + cfg: cfg, + } +} + +// ListenAndServe starts the gRPC server. +func (s *Server) ListenAndServe(ctx context.Context, cancel context.CancelFunc) error { + // Start listening + lis, err := net.Listen("tcp", s.cfg.Listen) + if chk.E(err) { + return err + } + s.listener = lis + log.I.F("gRPC database server listening on %s", s.cfg.Listen) + + // Handle graceful shutdown + go s.handleShutdown(ctx, cancel) + + // Serve gRPC + return s.grpcServer.Serve(lis) +} + +func (s *Server) handleShutdown(ctx context.Context, cancel context.CancelFunc) { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT) + + select { + case sig := <-sigs: + log.I.F("received signal %v, shutting down...", sig) + case <-ctx.Done(): + log.I.F("context cancelled, shutting down...") + } + + // Cancel context to stop all operations + cancel() + + // Gracefully stop gRPC server with timeout + stopped := make(chan struct{}) + go func() { + s.grpcServer.GracefulStop() + close(stopped) + }() + + select { + case <-stopped: + log.I.F("gRPC server stopped gracefully") + case <-time.After(5 * time.Second): + log.W.F("gRPC graceful stop timed out, forcing stop") + s.grpcServer.Stop() + } + + // Sync and close database + log.I.F("syncing database...") + if err := s.db.Sync(); chk.E(err) { + log.W.F("failed to sync database: %v", err) + } + log.I.F("closing database...") + if err := s.db.Close(); chk.E(err) { + log.W.F("failed to close database: %v", err) + } + log.I.F("shutdown complete") +} + +// Stop stops the server. +func (s *Server) Stop() { + s.grpcServer.Stop() +} diff --git a/pkg/database/server/service.go b/pkg/database/server/service.go new file mode 100644 index 0000000..51cd7cf --- /dev/null +++ b/pkg/database/server/service.go @@ -0,0 +1,731 @@ +package server + +import ( + "context" + "io" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "lol.mleku.dev/chk" + "lol.mleku.dev/log" + + "next.orly.dev/pkg/database" + orlydbv1 "next.orly.dev/pkg/proto/orlydb/v1" +) + +// DatabaseService implements the orlydbv1.DatabaseServiceServer interface. +type DatabaseService struct { + orlydbv1.UnimplementedDatabaseServiceServer + db database.Database + cfg *Config +} + +// NewDatabaseService creates a new database service. +func NewDatabaseService(db database.Database, cfg *Config) *DatabaseService { + return &DatabaseService{ + db: db, + cfg: cfg, + } +} + +// === Lifecycle Methods === + +func (s *DatabaseService) GetPath(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.PathResponse, error) { + return &orlydbv1.PathResponse{Path: s.db.Path()}, nil +} + +func (s *DatabaseService) Sync(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.Empty, error) { + if err := s.db.Sync(); err != nil { + return nil, status.Errorf(codes.Internal, "sync failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) Ready(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.ReadyResponse, error) { + // Check if ready channel is closed + select { + case <-s.db.Ready(): + return &orlydbv1.ReadyResponse{Ready: true}, nil + default: + return &orlydbv1.ReadyResponse{Ready: false}, nil + } +} + +func (s *DatabaseService) SetLogLevel(ctx context.Context, req *orlydbv1.SetLogLevelRequest) (*orlydbv1.Empty, error) { + s.db.SetLogLevel(req.Level) + return &orlydbv1.Empty{}, nil +} + +// === Event Storage === + +func (s *DatabaseService) SaveEvent(ctx context.Context, req *orlydbv1.SaveEventRequest) (*orlydbv1.SaveEventResponse, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + exists, err := s.db.SaveEvent(ctx, ev) + if err != nil { + return nil, status.Errorf(codes.Internal, "save event failed: %v", err) + } + return &orlydbv1.SaveEventResponse{Exists: exists}, nil +} + +func (s *DatabaseService) GetSerialsFromFilter(ctx context.Context, req *orlydbv1.GetSerialsFromFilterRequest) (*orlydbv1.SerialList, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + serials, err := s.db.GetSerialsFromFilter(f) + if err != nil { + return nil, status.Errorf(codes.Internal, "get serials failed: %v", err) + } + return orlydbv1.Uint40sToProto(serials), nil +} + +func (s *DatabaseService) WouldReplaceEvent(ctx context.Context, req *orlydbv1.WouldReplaceEventRequest) (*orlydbv1.WouldReplaceEventResponse, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + wouldReplace, replacedSerials, err := s.db.WouldReplaceEvent(ev) + if err != nil { + return nil, status.Errorf(codes.Internal, "would replace check failed: %v", err) + } + resp := &orlydbv1.WouldReplaceEventResponse{ + WouldReplace: wouldReplace, + } + for _, ser := range replacedSerials { + resp.ReplacedSerials = append(resp.ReplacedSerials, ser.Get()) + } + return resp, nil +} + +// === Event Queries (Streaming) === + +func (s *DatabaseService) QueryEvents(req *orlydbv1.QueryEventsRequest, stream orlydbv1.DatabaseService_QueryEventsServer) error { + f := orlydbv1.ProtoToFilter(req.Filter) + events, err := s.db.QueryEvents(stream.Context(), f) + if err != nil { + return status.Errorf(codes.Internal, "query events failed: %v", err) + } + return s.streamEvents(orlydbv1.EventsToProto(events), stream) +} + +func (s *DatabaseService) QueryAllVersions(req *orlydbv1.QueryEventsRequest, stream orlydbv1.DatabaseService_QueryAllVersionsServer) error { + f := orlydbv1.ProtoToFilter(req.Filter) + events, err := s.db.QueryAllVersions(stream.Context(), f) + if err != nil { + return status.Errorf(codes.Internal, "query all versions failed: %v", err) + } + return s.streamEvents(orlydbv1.EventsToProto(events), stream) +} + +func (s *DatabaseService) QueryEventsWithOptions(req *orlydbv1.QueryEventsWithOptionsRequest, stream orlydbv1.DatabaseService_QueryEventsWithOptionsServer) error { + f := orlydbv1.ProtoToFilter(req.Filter) + events, err := s.db.QueryEventsWithOptions(stream.Context(), f, req.IncludeDeleteEvents, req.ShowAllVersions) + if err != nil { + return status.Errorf(codes.Internal, "query events with options failed: %v", err) + } + return s.streamEvents(orlydbv1.EventsToProto(events), stream) +} + +func (s *DatabaseService) QueryDeleteEventsByTargetId(req *orlydbv1.QueryDeleteEventsByTargetIdRequest, stream orlydbv1.DatabaseService_QueryDeleteEventsByTargetIdServer) error { + events, err := s.db.QueryDeleteEventsByTargetId(stream.Context(), req.TargetEventId) + if err != nil { + return status.Errorf(codes.Internal, "query delete events failed: %v", err) + } + return s.streamEvents(orlydbv1.EventsToProto(events), stream) +} + +func (s *DatabaseService) QueryForSerials(ctx context.Context, req *orlydbv1.QueryEventsRequest) (*orlydbv1.SerialList, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + serials, err := s.db.QueryForSerials(ctx, f) + if err != nil { + return nil, status.Errorf(codes.Internal, "query for serials failed: %v", err) + } + return orlydbv1.Uint40sToProto(serials), nil +} + +func (s *DatabaseService) QueryForIds(ctx context.Context, req *orlydbv1.QueryEventsRequest) (*orlydbv1.IdPkTsList, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + idPkTs, err := s.db.QueryForIds(ctx, f) + if err != nil { + return nil, status.Errorf(codes.Internal, "query for ids failed: %v", err) + } + return orlydbv1.IdPkTsListToProto(idPkTs), nil +} + +func (s *DatabaseService) CountEvents(ctx context.Context, req *orlydbv1.QueryEventsRequest) (*orlydbv1.CountEventsResponse, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + count, approximate, err := s.db.CountEvents(ctx, f) + if err != nil { + return nil, status.Errorf(codes.Internal, "count events failed: %v", err) + } + return &orlydbv1.CountEventsResponse{ + Count: int32(count), + Approximate: approximate, + }, nil +} + +// === Event Retrieval by Serial === + +func (s *DatabaseService) FetchEventBySerial(ctx context.Context, req *orlydbv1.FetchEventBySerialRequest) (*orlydbv1.FetchEventBySerialResponse, error) { + ser := orlydbv1.ProtoToUint40(&orlydbv1.Uint40{Value: req.Serial}) + ev, err := s.db.FetchEventBySerial(ser) + if err != nil { + return nil, status.Errorf(codes.Internal, "fetch event by serial failed: %v", err) + } + return &orlydbv1.FetchEventBySerialResponse{ + Event: orlydbv1.EventToProto(ev), + Found: ev != nil, + }, nil +} + +func (s *DatabaseService) FetchEventsBySerials(ctx context.Context, req *orlydbv1.FetchEventsBySerialRequest) (*orlydbv1.EventMap, error) { + serials := orlydbv1.ProtoToUint40s(&orlydbv1.SerialList{Serials: req.Serials}) + events, err := s.db.FetchEventsBySerials(serials) + if err != nil { + return nil, status.Errorf(codes.Internal, "fetch events by serials failed: %v", err) + } + return orlydbv1.EventMapToProto(events), nil +} + +func (s *DatabaseService) GetSerialById(ctx context.Context, req *orlydbv1.GetSerialByIdRequest) (*orlydbv1.GetSerialByIdResponse, error) { + ser, err := s.db.GetSerialById(req.Id) + if err != nil { + return nil, status.Errorf(codes.Internal, "get serial by id failed: %v", err) + } + if ser == nil { + return &orlydbv1.GetSerialByIdResponse{Found: false}, nil + } + return &orlydbv1.GetSerialByIdResponse{ + Serial: ser.Get(), + Found: true, + }, nil +} + +func (s *DatabaseService) GetSerialsByIds(ctx context.Context, req *orlydbv1.GetSerialsByIdsRequest) (*orlydbv1.SerialMap, error) { + // Convert request IDs to tag format + ids := orlydbv1.BytesToTag(req.Ids) + serials, err := s.db.GetSerialsByIds(ids) + if err != nil { + return nil, status.Errorf(codes.Internal, "get serials by ids failed: %v", err) + } + result := &orlydbv1.SerialMap{ + Serials: make(map[string]uint64), + } + for k, v := range serials { + if v != nil { + result.Serials[k] = v.Get() + } + } + return result, nil +} + +func (s *DatabaseService) GetSerialsByRange(ctx context.Context, req *orlydbv1.GetSerialsByRangeRequest) (*orlydbv1.SerialList, error) { + r := orlydbv1.ProtoToRange(req.Range) + serials, err := s.db.GetSerialsByRange(r) + if err != nil { + return nil, status.Errorf(codes.Internal, "get serials by range failed: %v", err) + } + return orlydbv1.Uint40sToProto(serials), nil +} + +func (s *DatabaseService) GetFullIdPubkeyBySerial(ctx context.Context, req *orlydbv1.GetFullIdPubkeyBySerialRequest) (*orlydbv1.IdPkTs, error) { + ser := orlydbv1.ProtoToUint40(&orlydbv1.Uint40{Value: req.Serial}) + idPkTs, err := s.db.GetFullIdPubkeyBySerial(ser) + if err != nil { + return nil, status.Errorf(codes.Internal, "get full id pubkey by serial failed: %v", err) + } + return orlydbv1.IdPkTsToProto(idPkTs), nil +} + +func (s *DatabaseService) GetFullIdPubkeyBySerials(ctx context.Context, req *orlydbv1.GetFullIdPubkeyBySerialsRequest) (*orlydbv1.IdPkTsList, error) { + serials := orlydbv1.ProtoToUint40s(&orlydbv1.SerialList{Serials: req.Serials}) + idPkTs, err := s.db.GetFullIdPubkeyBySerials(serials) + if err != nil { + return nil, status.Errorf(codes.Internal, "get full id pubkey by serials failed: %v", err) + } + return orlydbv1.IdPkTsListToProto(idPkTs), nil +} + +// === Event Deletion === + +func (s *DatabaseService) DeleteEvent(ctx context.Context, req *orlydbv1.DeleteEventRequest) (*orlydbv1.Empty, error) { + if err := s.db.DeleteEvent(ctx, req.EventId); err != nil { + return nil, status.Errorf(codes.Internal, "delete event failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) DeleteEventBySerial(ctx context.Context, req *orlydbv1.DeleteEventBySerialRequest) (*orlydbv1.Empty, error) { + ser := orlydbv1.ProtoToUint40(&orlydbv1.Uint40{Value: req.Serial}) + ev := orlydbv1.ProtoToEvent(req.Event) + if err := s.db.DeleteEventBySerial(ctx, ser, ev); err != nil { + return nil, status.Errorf(codes.Internal, "delete event by serial failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) DeleteExpired(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.Empty, error) { + s.db.DeleteExpired() + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) ProcessDelete(ctx context.Context, req *orlydbv1.ProcessDeleteRequest) (*orlydbv1.Empty, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + if err := s.db.ProcessDelete(ev, req.Admins); err != nil { + return nil, status.Errorf(codes.Internal, "process delete failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) CheckForDeleted(ctx context.Context, req *orlydbv1.CheckForDeletedRequest) (*orlydbv1.Empty, error) { + ev := orlydbv1.ProtoToEvent(req.Event) + if err := s.db.CheckForDeleted(ev, req.Admins); err != nil { + return nil, status.Errorf(codes.Internal, "check for deleted failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +// === Import/Export === + +func (s *DatabaseService) Import(stream orlydbv1.DatabaseService_ImportServer) error { + pr, pw := io.Pipe() + + // Goroutine to read from gRPC stream and write to pipe + go func() { + defer pw.Close() + for { + chunk, err := stream.Recv() + if err == io.EOF { + return + } + if err != nil { + log.E.F("import stream error: %v", err) + pw.CloseWithError(err) + return + } + if _, err := pw.Write(chunk.Data); chk.E(err) { + return + } + } + }() + + // Import from pipe + s.db.Import(pr) + + return stream.SendAndClose(&orlydbv1.ImportResponse{ + EventsImported: 0, // TODO: Track count + EventsSkipped: 0, + }) +} + +func (s *DatabaseService) Export(req *orlydbv1.ExportRequest, stream orlydbv1.DatabaseService_ExportServer) error { + pr, pw := io.Pipe() + + // Goroutine to export to pipe + go func() { + defer pw.Close() + s.db.Export(stream.Context(), pw, req.Pubkeys...) + }() + + // Read from pipe and send to stream + buf := make([]byte, 64*1024) // 64KB chunks + for { + n, err := pr.Read(buf) + if err == io.EOF { + return nil + } + if err != nil { + return status.Errorf(codes.Internal, "export failed: %v", err) + } + if err := stream.Send(&orlydbv1.ExportChunk{Data: buf[:n]}); err != nil { + return err + } + } +} + +func (s *DatabaseService) ImportEventsFromStrings(ctx context.Context, req *orlydbv1.ImportEventsFromStringsRequest) (*orlydbv1.ImportResponse, error) { + // Note: We can't pass policy manager over gRPC, so we pass nil + if err := s.db.ImportEventsFromStrings(ctx, req.EventJsons, nil); err != nil { + return nil, status.Errorf(codes.Internal, "import events from strings failed: %v", err) + } + return &orlydbv1.ImportResponse{ + EventsImported: int64(len(req.EventJsons)), + }, nil +} + +// === Relay Identity === + +func (s *DatabaseService) GetRelayIdentitySecret(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.GetRelayIdentitySecretResponse, error) { + secret, err := s.db.GetRelayIdentitySecret() + if err != nil { + return nil, status.Errorf(codes.Internal, "get relay identity secret failed: %v", err) + } + return &orlydbv1.GetRelayIdentitySecretResponse{SecretKey: secret}, nil +} + +func (s *DatabaseService) SetRelayIdentitySecret(ctx context.Context, req *orlydbv1.SetRelayIdentitySecretRequest) (*orlydbv1.Empty, error) { + if err := s.db.SetRelayIdentitySecret(req.SecretKey); err != nil { + return nil, status.Errorf(codes.Internal, "set relay identity secret failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetOrCreateRelayIdentitySecret(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.GetRelayIdentitySecretResponse, error) { + secret, err := s.db.GetOrCreateRelayIdentitySecret() + if err != nil { + return nil, status.Errorf(codes.Internal, "get or create relay identity secret failed: %v", err) + } + return &orlydbv1.GetRelayIdentitySecretResponse{SecretKey: secret}, nil +} + +// === Markers === + +func (s *DatabaseService) SetMarker(ctx context.Context, req *orlydbv1.SetMarkerRequest) (*orlydbv1.Empty, error) { + if err := s.db.SetMarker(req.Key, req.Value); err != nil { + return nil, status.Errorf(codes.Internal, "set marker failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetMarker(ctx context.Context, req *orlydbv1.GetMarkerRequest) (*orlydbv1.GetMarkerResponse, error) { + value, err := s.db.GetMarker(req.Key) + if err != nil { + return nil, status.Errorf(codes.Internal, "get marker failed: %v", err) + } + return &orlydbv1.GetMarkerResponse{ + Value: value, + Found: value != nil, + }, nil +} + +func (s *DatabaseService) HasMarker(ctx context.Context, req *orlydbv1.HasMarkerRequest) (*orlydbv1.HasMarkerResponse, error) { + exists := s.db.HasMarker(req.Key) + return &orlydbv1.HasMarkerResponse{Exists: exists}, nil +} + +func (s *DatabaseService) DeleteMarker(ctx context.Context, req *orlydbv1.DeleteMarkerRequest) (*orlydbv1.Empty, error) { + if err := s.db.DeleteMarker(req.Key); err != nil { + return nil, status.Errorf(codes.Internal, "delete marker failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +// === Subscriptions === + +func (s *DatabaseService) GetSubscription(ctx context.Context, req *orlydbv1.GetSubscriptionRequest) (*orlydbv1.Subscription, error) { + sub, err := s.db.GetSubscription(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "get subscription failed: %v", err) + } + return orlydbv1.SubscriptionToProto(sub, req.Pubkey), nil +} + +func (s *DatabaseService) IsSubscriptionActive(ctx context.Context, req *orlydbv1.IsSubscriptionActiveRequest) (*orlydbv1.IsSubscriptionActiveResponse, error) { + active, err := s.db.IsSubscriptionActive(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "is subscription active failed: %v", err) + } + return &orlydbv1.IsSubscriptionActiveResponse{Active: active}, nil +} + +func (s *DatabaseService) ExtendSubscription(ctx context.Context, req *orlydbv1.ExtendSubscriptionRequest) (*orlydbv1.Empty, error) { + if err := s.db.ExtendSubscription(req.Pubkey, int(req.Days)); err != nil { + return nil, status.Errorf(codes.Internal, "extend subscription failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) RecordPayment(ctx context.Context, req *orlydbv1.RecordPaymentRequest) (*orlydbv1.Empty, error) { + if err := s.db.RecordPayment(req.Pubkey, req.Amount, req.Invoice, req.Preimage); err != nil { + return nil, status.Errorf(codes.Internal, "record payment failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetPaymentHistory(ctx context.Context, req *orlydbv1.GetPaymentHistoryRequest) (*orlydbv1.PaymentList, error) { + payments, err := s.db.GetPaymentHistory(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "get payment history failed: %v", err) + } + return orlydbv1.PaymentListToProto(payments), nil +} + +func (s *DatabaseService) ExtendBlossomSubscription(ctx context.Context, req *orlydbv1.ExtendBlossomSubscriptionRequest) (*orlydbv1.Empty, error) { + if err := s.db.ExtendBlossomSubscription(req.Pubkey, req.Tier, req.StorageMb, int(req.DaysExtended)); err != nil { + return nil, status.Errorf(codes.Internal, "extend blossom subscription failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetBlossomStorageQuota(ctx context.Context, req *orlydbv1.GetBlossomStorageQuotaRequest) (*orlydbv1.GetBlossomStorageQuotaResponse, error) { + quota, err := s.db.GetBlossomStorageQuota(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "get blossom storage quota failed: %v", err) + } + return &orlydbv1.GetBlossomStorageQuotaResponse{QuotaMb: quota}, nil +} + +func (s *DatabaseService) IsFirstTimeUser(ctx context.Context, req *orlydbv1.IsFirstTimeUserRequest) (*orlydbv1.IsFirstTimeUserResponse, error) { + firstTime, err := s.db.IsFirstTimeUser(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "is first time user failed: %v", err) + } + return &orlydbv1.IsFirstTimeUserResponse{FirstTime: firstTime}, nil +} + +// === NIP-43 === + +func (s *DatabaseService) AddNIP43Member(ctx context.Context, req *orlydbv1.AddNIP43MemberRequest) (*orlydbv1.Empty, error) { + if err := s.db.AddNIP43Member(req.Pubkey, req.InviteCode); err != nil { + return nil, status.Errorf(codes.Internal, "add NIP-43 member failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) RemoveNIP43Member(ctx context.Context, req *orlydbv1.RemoveNIP43MemberRequest) (*orlydbv1.Empty, error) { + if err := s.db.RemoveNIP43Member(req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "remove NIP-43 member failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) IsNIP43Member(ctx context.Context, req *orlydbv1.IsNIP43MemberRequest) (*orlydbv1.IsNIP43MemberResponse, error) { + isMember, err := s.db.IsNIP43Member(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "is NIP-43 member failed: %v", err) + } + return &orlydbv1.IsNIP43MemberResponse{IsMember: isMember}, nil +} + +func (s *DatabaseService) GetNIP43Membership(ctx context.Context, req *orlydbv1.GetNIP43MembershipRequest) (*orlydbv1.NIP43Membership, error) { + membership, err := s.db.GetNIP43Membership(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "get NIP-43 membership failed: %v", err) + } + return orlydbv1.NIP43MembershipToProto(membership), nil +} + +func (s *DatabaseService) GetAllNIP43Members(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.PubkeyList, error) { + members, err := s.db.GetAllNIP43Members() + if err != nil { + return nil, status.Errorf(codes.Internal, "get all NIP-43 members failed: %v", err) + } + return &orlydbv1.PubkeyList{Pubkeys: members}, nil +} + +func (s *DatabaseService) StoreInviteCode(ctx context.Context, req *orlydbv1.StoreInviteCodeRequest) (*orlydbv1.Empty, error) { + expiresAt := orlydbv1.TimeFromUnix(req.ExpiresAt) + if err := s.db.StoreInviteCode(req.Code, expiresAt); err != nil { + return nil, status.Errorf(codes.Internal, "store invite code failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) ValidateInviteCode(ctx context.Context, req *orlydbv1.ValidateInviteCodeRequest) (*orlydbv1.ValidateInviteCodeResponse, error) { + valid, err := s.db.ValidateInviteCode(req.Code) + if err != nil { + return nil, status.Errorf(codes.Internal, "validate invite code failed: %v", err) + } + return &orlydbv1.ValidateInviteCodeResponse{Valid: valid}, nil +} + +func (s *DatabaseService) DeleteInviteCode(ctx context.Context, req *orlydbv1.DeleteInviteCodeRequest) (*orlydbv1.Empty, error) { + if err := s.db.DeleteInviteCode(req.Code); err != nil { + return nil, status.Errorf(codes.Internal, "delete invite code failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) PublishNIP43MembershipEvent(ctx context.Context, req *orlydbv1.PublishNIP43MembershipEventRequest) (*orlydbv1.Empty, error) { + if err := s.db.PublishNIP43MembershipEvent(int(req.Kind), req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "publish NIP-43 membership event failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +// === Query Cache === + +func (s *DatabaseService) GetCachedJSON(ctx context.Context, req *orlydbv1.GetCachedJSONRequest) (*orlydbv1.GetCachedJSONResponse, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + jsonItems, found := s.db.GetCachedJSON(f) + return &orlydbv1.GetCachedJSONResponse{ + JsonItems: jsonItems, + Found: found, + }, nil +} + +func (s *DatabaseService) CacheMarshaledJSON(ctx context.Context, req *orlydbv1.CacheMarshaledJSONRequest) (*orlydbv1.Empty, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + s.db.CacheMarshaledJSON(f, req.JsonItems) + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetCachedEvents(ctx context.Context, req *orlydbv1.GetCachedEventsRequest) (*orlydbv1.GetCachedEventsResponse, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + events, found := s.db.GetCachedEvents(f) + return &orlydbv1.GetCachedEventsResponse{ + Events: orlydbv1.EventsToProto(events), + Found: found, + }, nil +} + +func (s *DatabaseService) CacheEvents(ctx context.Context, req *orlydbv1.CacheEventsRequest) (*orlydbv1.Empty, error) { + f := orlydbv1.ProtoToFilter(req.Filter) + events := orlydbv1.ProtoToEvents(req.Events) + s.db.CacheEvents(f, events) + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) InvalidateQueryCache(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.Empty, error) { + s.db.InvalidateQueryCache() + return &orlydbv1.Empty{}, nil +} + +// === Access Tracking === + +func (s *DatabaseService) RecordEventAccess(ctx context.Context, req *orlydbv1.RecordEventAccessRequest) (*orlydbv1.Empty, error) { + if err := s.db.RecordEventAccess(req.Serial, req.ConnectionId); err != nil { + return nil, status.Errorf(codes.Internal, "record event access failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetEventAccessInfo(ctx context.Context, req *orlydbv1.GetEventAccessInfoRequest) (*orlydbv1.GetEventAccessInfoResponse, error) { + lastAccess, accessCount, err := s.db.GetEventAccessInfo(req.Serial) + if err != nil { + return nil, status.Errorf(codes.Internal, "get event access info failed: %v", err) + } + return &orlydbv1.GetEventAccessInfoResponse{ + LastAccess: lastAccess, + AccessCount: accessCount, + }, nil +} + +func (s *DatabaseService) GetLeastAccessedEvents(ctx context.Context, req *orlydbv1.GetLeastAccessedEventsRequest) (*orlydbv1.SerialList, error) { + serials, err := s.db.GetLeastAccessedEvents(int(req.Limit), req.MinAgeSec) + if err != nil { + return nil, status.Errorf(codes.Internal, "get least accessed events failed: %v", err) + } + return &orlydbv1.SerialList{Serials: serials}, nil +} + +// === Utility === + +func (s *DatabaseService) EventIdsBySerial(ctx context.Context, req *orlydbv1.EventIdsBySerialRequest) (*orlydbv1.EventIdsBySerialResponse, error) { + eventIds, err := s.db.EventIdsBySerial(req.Start, int(req.Count)) + if err != nil { + return nil, status.Errorf(codes.Internal, "event ids by serial failed: %v", err) + } + return &orlydbv1.EventIdsBySerialResponse{EventIds: eventIds}, nil +} + +func (s *DatabaseService) RunMigrations(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.Empty, error) { + s.db.RunMigrations() + return &orlydbv1.Empty{}, nil +} + +// === Blob Storage (Blossom) === + +func (s *DatabaseService) SaveBlob(ctx context.Context, req *orlydbv1.SaveBlobRequest) (*orlydbv1.Empty, error) { + if err := s.db.SaveBlob(req.Sha256Hash, req.Data, req.Pubkey, req.MimeType, req.Extension); err != nil { + return nil, status.Errorf(codes.Internal, "save blob failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) GetBlob(ctx context.Context, req *orlydbv1.GetBlobRequest) (*orlydbv1.GetBlobResponse, error) { + data, metadata, err := s.db.GetBlob(req.Sha256Hash) + if err != nil { + // Return not found as a response, not an error + return &orlydbv1.GetBlobResponse{Found: false}, nil + } + return &orlydbv1.GetBlobResponse{ + Found: true, + Data: data, + Metadata: orlydbv1.BlobMetadataToProto(metadata), + }, nil +} + +func (s *DatabaseService) HasBlob(ctx context.Context, req *orlydbv1.HasBlobRequest) (*orlydbv1.HasBlobResponse, error) { + exists, err := s.db.HasBlob(req.Sha256Hash) + if err != nil { + return nil, status.Errorf(codes.Internal, "has blob failed: %v", err) + } + return &orlydbv1.HasBlobResponse{Exists: exists}, nil +} + +func (s *DatabaseService) DeleteBlob(ctx context.Context, req *orlydbv1.DeleteBlobRequest) (*orlydbv1.Empty, error) { + if err := s.db.DeleteBlob(req.Sha256Hash, req.Pubkey); err != nil { + return nil, status.Errorf(codes.Internal, "delete blob failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) ListBlobs(ctx context.Context, req *orlydbv1.ListBlobsRequest) (*orlydbv1.ListBlobsResponse, error) { + descriptors, err := s.db.ListBlobs(req.Pubkey, req.Since, req.Until) + if err != nil { + return nil, status.Errorf(codes.Internal, "list blobs failed: %v", err) + } + return &orlydbv1.ListBlobsResponse{ + Descriptors: orlydbv1.BlobDescriptorListToProto(descriptors), + }, nil +} + +func (s *DatabaseService) GetBlobMetadata(ctx context.Context, req *orlydbv1.GetBlobMetadataRequest) (*orlydbv1.BlobMetadata, error) { + metadata, err := s.db.GetBlobMetadata(req.Sha256Hash) + if err != nil { + return nil, status.Errorf(codes.NotFound, "blob metadata not found: %v", err) + } + return orlydbv1.BlobMetadataToProto(metadata), nil +} + +func (s *DatabaseService) GetTotalBlobStorageUsed(ctx context.Context, req *orlydbv1.GetTotalBlobStorageUsedRequest) (*orlydbv1.GetTotalBlobStorageUsedResponse, error) { + totalMB, err := s.db.GetTotalBlobStorageUsed(req.Pubkey) + if err != nil { + return nil, status.Errorf(codes.Internal, "get total blob storage used failed: %v", err) + } + return &orlydbv1.GetTotalBlobStorageUsedResponse{TotalMb: totalMB}, nil +} + +func (s *DatabaseService) SaveBlobReport(ctx context.Context, req *orlydbv1.SaveBlobReportRequest) (*orlydbv1.Empty, error) { + if err := s.db.SaveBlobReport(req.Sha256Hash, req.ReportData); err != nil { + return nil, status.Errorf(codes.Internal, "save blob report failed: %v", err) + } + return &orlydbv1.Empty{}, nil +} + +func (s *DatabaseService) ListAllBlobUserStats(ctx context.Context, req *orlydbv1.Empty) (*orlydbv1.ListAllBlobUserStatsResponse, error) { + stats, err := s.db.ListAllBlobUserStats() + if err != nil { + return nil, status.Errorf(codes.Internal, "list all blob user stats failed: %v", err) + } + return &orlydbv1.ListAllBlobUserStatsResponse{ + Stats: orlydbv1.UserBlobStatsListToProto(stats), + }, nil +} + +// === Helper Methods === + +// streamEvents is a helper to stream events in batches. +type eventStreamer interface { + Send(*orlydbv1.EventBatch) error + Context() context.Context +} + +func (s *DatabaseService) streamEvents(events []*orlydbv1.Event, stream eventStreamer) error { + batchSize := s.cfg.StreamBatchSize + if batchSize == 0 { + batchSize = 100 + } + + for i := 0; i < len(events); i += batchSize { + end := i + batchSize + if end > len(events) { + end = len(events) + } + + batch := &orlydbv1.EventBatch{ + Events: events[i:end], + } + + if err := stream.Send(batch); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/proto/orlyacl/v1/acl.pb.go b/pkg/proto/orlyacl/v1/acl.pb.go new file mode 100644 index 0000000..2b9d893 --- /dev/null +++ b/pkg/proto/orlyacl/v1/acl.pb.go @@ -0,0 +1,250 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: orlyacl/v1/acl.proto + +package orlyaclv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var File_orlyacl_v1_acl_proto protoreflect.FileDescriptor + +const file_orlyacl_v1_acl_proto_rawDesc = "" + + "\n" + + "\x14orlyacl/v1/acl.proto\x12\n" + + "orlyacl.v1\x1a\x16orlyacl/v1/types.proto2\x91\x19\n" + + "\n" + + "ACLService\x12Q\n" + + "\x0eGetAccessLevel\x12\x1e.orlyacl.v1.AccessLevelRequest\x1a\x1f.orlyacl.v1.AccessLevelResponse\x12N\n" + + "\vCheckPolicy\x12\x1e.orlyacl.v1.PolicyCheckRequest\x1a\x1f.orlyacl.v1.PolicyCheckResponse\x12<\n" + + "\n" + + "GetACLInfo\x12\x11.orlyacl.v1.Empty\x1a\x1b.orlyacl.v1.ACLInfoResponse\x126\n" + + "\aGetMode\x12\x11.orlyacl.v1.Empty\x1a\x18.orlyacl.v1.ModeResponse\x125\n" + + "\x05Ready\x12\x11.orlyacl.v1.Empty\x1a\x19.orlyacl.v1.ReadyResponse\x12W\n" + + "\x10GetThrottleDelay\x12 .orlyacl.v1.ThrottleDelayRequest\x1a!.orlyacl.v1.ThrottleDelayResponse\x12<\n" + + "\tAddFollow\x12\x1c.orlyacl.v1.AddFollowRequest\x1a\x11.orlyacl.v1.Empty\x12L\n" + + "\x12GetFollowedPubkeys\x12\x11.orlyacl.v1.Empty\x1a#.orlyacl.v1.FollowedPubkeysResponse\x12D\n" + + "\x0eGetAdminRelays\x12\x11.orlyacl.v1.Empty\x1a\x1f.orlyacl.v1.AdminRelaysResponse\x12<\n" + + "\tBanPubkey\x12\x1c.orlyacl.v1.BanPubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12;\n" + + "\vUnbanPubkey\x12\x19.orlyacl.v1.PubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12M\n" + + "\x11ListBannedPubkeys\x12\x11.orlyacl.v1.Empty\x1a%.orlyacl.v1.ListBannedPubkeysResponse\x12@\n" + + "\vAllowPubkey\x12\x1e.orlyacl.v1.AllowPubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12>\n" + + "\x0eDisallowPubkey\x12\x19.orlyacl.v1.PubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12O\n" + + "\x12ListAllowedPubkeys\x12\x11.orlyacl.v1.Empty\x1a&.orlyacl.v1.ListAllowedPubkeysResponse\x12:\n" + + "\bBanEvent\x12\x1b.orlyacl.v1.BanEventRequest\x1a\x11.orlyacl.v1.Empty\x129\n" + + "\n" + + "UnbanEvent\x12\x18.orlyacl.v1.EventRequest\x1a\x11.orlyacl.v1.Empty\x12K\n" + + "\x10ListBannedEvents\x12\x11.orlyacl.v1.Empty\x1a$.orlyacl.v1.ListBannedEventsResponse\x12<\n" + + "\n" + + "AllowEvent\x12\x1b.orlyacl.v1.BanEventRequest\x1a\x11.orlyacl.v1.Empty\x12<\n" + + "\rDisallowEvent\x12\x18.orlyacl.v1.EventRequest\x1a\x11.orlyacl.v1.Empty\x12M\n" + + "\x11ListAllowedEvents\x12\x11.orlyacl.v1.Empty\x1a%.orlyacl.v1.ListAllowedEventsResponse\x128\n" + + "\aBlockIP\x12\x1a.orlyacl.v1.BlockIPRequest\x1a\x11.orlyacl.v1.Empty\x125\n" + + "\tUnblockIP\x12\x15.orlyacl.v1.IPRequest\x1a\x11.orlyacl.v1.Empty\x12G\n" + + "\x0eListBlockedIPs\x12\x11.orlyacl.v1.Empty\x1a\".orlyacl.v1.ListBlockedIPsResponse\x12<\n" + + "\tAllowKind\x12\x1c.orlyacl.v1.AllowKindRequest\x1a\x11.orlyacl.v1.Empty\x12:\n" + + "\fDisallowKind\x12\x17.orlyacl.v1.KindRequest\x1a\x11.orlyacl.v1.Empty\x12K\n" + + "\x10ListAllowedKinds\x12\x11.orlyacl.v1.Empty\x1a$.orlyacl.v1.ListAllowedKindsResponse\x12J\n" + + "\x10UpdatePeerAdmins\x12#.orlyacl.v1.UpdatePeerAdminsRequest\x1a\x11.orlyacl.v1.Empty\x12@\n" + + "\vTrustPubkey\x12\x1e.orlyacl.v1.TrustPubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12=\n" + + "\rUntrustPubkey\x12\x19.orlyacl.v1.PubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12O\n" + + "\x12ListTrustedPubkeys\x12\x11.orlyacl.v1.Empty\x1a&.orlyacl.v1.ListTrustedPubkeysResponse\x12H\n" + + "\x0fBlacklistPubkey\x12\".orlyacl.v1.BlacklistPubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12A\n" + + "\x11UnblacklistPubkey\x12\x19.orlyacl.v1.PubkeyRequest\x1a\x11.orlyacl.v1.Empty\x12W\n" + + "\x16ListBlacklistedPubkeys\x12\x11.orlyacl.v1.Empty\x1a*.orlyacl.v1.ListBlacklistedPubkeysResponse\x12:\n" + + "\bMarkSpam\x12\x1b.orlyacl.v1.MarkSpamRequest\x1a\x11.orlyacl.v1.Empty\x129\n" + + "\n" + + "UnmarkSpam\x12\x18.orlyacl.v1.EventRequest\x1a\x11.orlyacl.v1.Empty\x12G\n" + + "\x0eListSpamEvents\x12\x11.orlyacl.v1.Empty\x1a\".orlyacl.v1.ListSpamEventsResponse\x12W\n" + + "\x0eRateLimitCheck\x12!.orlyacl.v1.RateLimitCheckRequest\x1a\".orlyacl.v1.RateLimitCheckResponse\x12G\n" + + "\x12ProcessConfigEvent\x12\x1e.orlyacl.v1.ConfigEventRequest\x1a\x11.orlyacl.v1.Empty\x12B\n" + + "\x11GetCuratingConfig\x12\x11.orlyacl.v1.Empty\x1a\x1a.orlyacl.v1.CuratingConfig\x12C\n" + + "\x14IsCuratingConfigured\x12\x11.orlyacl.v1.Empty\x1a\x18.orlyacl.v1.BoolResponse\x12a\n" + + "\x15ListUnclassifiedUsers\x12\x1d.orlyacl.v1.PaginationRequest\x1a).orlyacl.v1.ListUnclassifiedUsersResponse\x12`\n" + + "\x12GetEventsForPubkey\x12%.orlyacl.v1.GetEventsForPubkeyRequest\x1a#.orlyacl.v1.EventsForPubkeyResponse\x12b\n" + + "\x15DeleteEventsForPubkey\x12(.orlyacl.v1.DeleteEventsForPubkeyRequest\x1a\x1f.orlyacl.v1.DeleteCountResponse\x12C\n" + + "\x0eScanAllPubkeys\x12\x11.orlyacl.v1.Empty\x1a\x1e.orlyacl.v1.ScanResultResponseB.Z,next.orly.dev/pkg/proto/orlyacl/v1;orlyaclv1b\x06proto3" + +var file_orlyacl_v1_acl_proto_goTypes = []any{ + (*AccessLevelRequest)(nil), // 0: orlyacl.v1.AccessLevelRequest + (*PolicyCheckRequest)(nil), // 1: orlyacl.v1.PolicyCheckRequest + (*Empty)(nil), // 2: orlyacl.v1.Empty + (*ThrottleDelayRequest)(nil), // 3: orlyacl.v1.ThrottleDelayRequest + (*AddFollowRequest)(nil), // 4: orlyacl.v1.AddFollowRequest + (*BanPubkeyRequest)(nil), // 5: orlyacl.v1.BanPubkeyRequest + (*PubkeyRequest)(nil), // 6: orlyacl.v1.PubkeyRequest + (*AllowPubkeyRequest)(nil), // 7: orlyacl.v1.AllowPubkeyRequest + (*BanEventRequest)(nil), // 8: orlyacl.v1.BanEventRequest + (*EventRequest)(nil), // 9: orlyacl.v1.EventRequest + (*BlockIPRequest)(nil), // 10: orlyacl.v1.BlockIPRequest + (*IPRequest)(nil), // 11: orlyacl.v1.IPRequest + (*AllowKindRequest)(nil), // 12: orlyacl.v1.AllowKindRequest + (*KindRequest)(nil), // 13: orlyacl.v1.KindRequest + (*UpdatePeerAdminsRequest)(nil), // 14: orlyacl.v1.UpdatePeerAdminsRequest + (*TrustPubkeyRequest)(nil), // 15: orlyacl.v1.TrustPubkeyRequest + (*BlacklistPubkeyRequest)(nil), // 16: orlyacl.v1.BlacklistPubkeyRequest + (*MarkSpamRequest)(nil), // 17: orlyacl.v1.MarkSpamRequest + (*RateLimitCheckRequest)(nil), // 18: orlyacl.v1.RateLimitCheckRequest + (*ConfigEventRequest)(nil), // 19: orlyacl.v1.ConfigEventRequest + (*PaginationRequest)(nil), // 20: orlyacl.v1.PaginationRequest + (*GetEventsForPubkeyRequest)(nil), // 21: orlyacl.v1.GetEventsForPubkeyRequest + (*DeleteEventsForPubkeyRequest)(nil), // 22: orlyacl.v1.DeleteEventsForPubkeyRequest + (*AccessLevelResponse)(nil), // 23: orlyacl.v1.AccessLevelResponse + (*PolicyCheckResponse)(nil), // 24: orlyacl.v1.PolicyCheckResponse + (*ACLInfoResponse)(nil), // 25: orlyacl.v1.ACLInfoResponse + (*ModeResponse)(nil), // 26: orlyacl.v1.ModeResponse + (*ReadyResponse)(nil), // 27: orlyacl.v1.ReadyResponse + (*ThrottleDelayResponse)(nil), // 28: orlyacl.v1.ThrottleDelayResponse + (*FollowedPubkeysResponse)(nil), // 29: orlyacl.v1.FollowedPubkeysResponse + (*AdminRelaysResponse)(nil), // 30: orlyacl.v1.AdminRelaysResponse + (*ListBannedPubkeysResponse)(nil), // 31: orlyacl.v1.ListBannedPubkeysResponse + (*ListAllowedPubkeysResponse)(nil), // 32: orlyacl.v1.ListAllowedPubkeysResponse + (*ListBannedEventsResponse)(nil), // 33: orlyacl.v1.ListBannedEventsResponse + (*ListAllowedEventsResponse)(nil), // 34: orlyacl.v1.ListAllowedEventsResponse + (*ListBlockedIPsResponse)(nil), // 35: orlyacl.v1.ListBlockedIPsResponse + (*ListAllowedKindsResponse)(nil), // 36: orlyacl.v1.ListAllowedKindsResponse + (*ListTrustedPubkeysResponse)(nil), // 37: orlyacl.v1.ListTrustedPubkeysResponse + (*ListBlacklistedPubkeysResponse)(nil), // 38: orlyacl.v1.ListBlacklistedPubkeysResponse + (*ListSpamEventsResponse)(nil), // 39: orlyacl.v1.ListSpamEventsResponse + (*RateLimitCheckResponse)(nil), // 40: orlyacl.v1.RateLimitCheckResponse + (*CuratingConfig)(nil), // 41: orlyacl.v1.CuratingConfig + (*BoolResponse)(nil), // 42: orlyacl.v1.BoolResponse + (*ListUnclassifiedUsersResponse)(nil), // 43: orlyacl.v1.ListUnclassifiedUsersResponse + (*EventsForPubkeyResponse)(nil), // 44: orlyacl.v1.EventsForPubkeyResponse + (*DeleteCountResponse)(nil), // 45: orlyacl.v1.DeleteCountResponse + (*ScanResultResponse)(nil), // 46: orlyacl.v1.ScanResultResponse +} +var file_orlyacl_v1_acl_proto_depIdxs = []int32{ + 0, // 0: orlyacl.v1.ACLService.GetAccessLevel:input_type -> orlyacl.v1.AccessLevelRequest + 1, // 1: orlyacl.v1.ACLService.CheckPolicy:input_type -> orlyacl.v1.PolicyCheckRequest + 2, // 2: orlyacl.v1.ACLService.GetACLInfo:input_type -> orlyacl.v1.Empty + 2, // 3: orlyacl.v1.ACLService.GetMode:input_type -> orlyacl.v1.Empty + 2, // 4: orlyacl.v1.ACLService.Ready:input_type -> orlyacl.v1.Empty + 3, // 5: orlyacl.v1.ACLService.GetThrottleDelay:input_type -> orlyacl.v1.ThrottleDelayRequest + 4, // 6: orlyacl.v1.ACLService.AddFollow:input_type -> orlyacl.v1.AddFollowRequest + 2, // 7: orlyacl.v1.ACLService.GetFollowedPubkeys:input_type -> orlyacl.v1.Empty + 2, // 8: orlyacl.v1.ACLService.GetAdminRelays:input_type -> orlyacl.v1.Empty + 5, // 9: orlyacl.v1.ACLService.BanPubkey:input_type -> orlyacl.v1.BanPubkeyRequest + 6, // 10: orlyacl.v1.ACLService.UnbanPubkey:input_type -> orlyacl.v1.PubkeyRequest + 2, // 11: orlyacl.v1.ACLService.ListBannedPubkeys:input_type -> orlyacl.v1.Empty + 7, // 12: orlyacl.v1.ACLService.AllowPubkey:input_type -> orlyacl.v1.AllowPubkeyRequest + 6, // 13: orlyacl.v1.ACLService.DisallowPubkey:input_type -> orlyacl.v1.PubkeyRequest + 2, // 14: orlyacl.v1.ACLService.ListAllowedPubkeys:input_type -> orlyacl.v1.Empty + 8, // 15: orlyacl.v1.ACLService.BanEvent:input_type -> orlyacl.v1.BanEventRequest + 9, // 16: orlyacl.v1.ACLService.UnbanEvent:input_type -> orlyacl.v1.EventRequest + 2, // 17: orlyacl.v1.ACLService.ListBannedEvents:input_type -> orlyacl.v1.Empty + 8, // 18: orlyacl.v1.ACLService.AllowEvent:input_type -> orlyacl.v1.BanEventRequest + 9, // 19: orlyacl.v1.ACLService.DisallowEvent:input_type -> orlyacl.v1.EventRequest + 2, // 20: orlyacl.v1.ACLService.ListAllowedEvents:input_type -> orlyacl.v1.Empty + 10, // 21: orlyacl.v1.ACLService.BlockIP:input_type -> orlyacl.v1.BlockIPRequest + 11, // 22: orlyacl.v1.ACLService.UnblockIP:input_type -> orlyacl.v1.IPRequest + 2, // 23: orlyacl.v1.ACLService.ListBlockedIPs:input_type -> orlyacl.v1.Empty + 12, // 24: orlyacl.v1.ACLService.AllowKind:input_type -> orlyacl.v1.AllowKindRequest + 13, // 25: orlyacl.v1.ACLService.DisallowKind:input_type -> orlyacl.v1.KindRequest + 2, // 26: orlyacl.v1.ACLService.ListAllowedKinds:input_type -> orlyacl.v1.Empty + 14, // 27: orlyacl.v1.ACLService.UpdatePeerAdmins:input_type -> orlyacl.v1.UpdatePeerAdminsRequest + 15, // 28: orlyacl.v1.ACLService.TrustPubkey:input_type -> orlyacl.v1.TrustPubkeyRequest + 6, // 29: orlyacl.v1.ACLService.UntrustPubkey:input_type -> orlyacl.v1.PubkeyRequest + 2, // 30: orlyacl.v1.ACLService.ListTrustedPubkeys:input_type -> orlyacl.v1.Empty + 16, // 31: orlyacl.v1.ACLService.BlacklistPubkey:input_type -> orlyacl.v1.BlacklistPubkeyRequest + 6, // 32: orlyacl.v1.ACLService.UnblacklistPubkey:input_type -> orlyacl.v1.PubkeyRequest + 2, // 33: orlyacl.v1.ACLService.ListBlacklistedPubkeys:input_type -> orlyacl.v1.Empty + 17, // 34: orlyacl.v1.ACLService.MarkSpam:input_type -> orlyacl.v1.MarkSpamRequest + 9, // 35: orlyacl.v1.ACLService.UnmarkSpam:input_type -> orlyacl.v1.EventRequest + 2, // 36: orlyacl.v1.ACLService.ListSpamEvents:input_type -> orlyacl.v1.Empty + 18, // 37: orlyacl.v1.ACLService.RateLimitCheck:input_type -> orlyacl.v1.RateLimitCheckRequest + 19, // 38: orlyacl.v1.ACLService.ProcessConfigEvent:input_type -> orlyacl.v1.ConfigEventRequest + 2, // 39: orlyacl.v1.ACLService.GetCuratingConfig:input_type -> orlyacl.v1.Empty + 2, // 40: orlyacl.v1.ACLService.IsCuratingConfigured:input_type -> orlyacl.v1.Empty + 20, // 41: orlyacl.v1.ACLService.ListUnclassifiedUsers:input_type -> orlyacl.v1.PaginationRequest + 21, // 42: orlyacl.v1.ACLService.GetEventsForPubkey:input_type -> orlyacl.v1.GetEventsForPubkeyRequest + 22, // 43: orlyacl.v1.ACLService.DeleteEventsForPubkey:input_type -> orlyacl.v1.DeleteEventsForPubkeyRequest + 2, // 44: orlyacl.v1.ACLService.ScanAllPubkeys:input_type -> orlyacl.v1.Empty + 23, // 45: orlyacl.v1.ACLService.GetAccessLevel:output_type -> orlyacl.v1.AccessLevelResponse + 24, // 46: orlyacl.v1.ACLService.CheckPolicy:output_type -> orlyacl.v1.PolicyCheckResponse + 25, // 47: orlyacl.v1.ACLService.GetACLInfo:output_type -> orlyacl.v1.ACLInfoResponse + 26, // 48: orlyacl.v1.ACLService.GetMode:output_type -> orlyacl.v1.ModeResponse + 27, // 49: orlyacl.v1.ACLService.Ready:output_type -> orlyacl.v1.ReadyResponse + 28, // 50: orlyacl.v1.ACLService.GetThrottleDelay:output_type -> orlyacl.v1.ThrottleDelayResponse + 2, // 51: orlyacl.v1.ACLService.AddFollow:output_type -> orlyacl.v1.Empty + 29, // 52: orlyacl.v1.ACLService.GetFollowedPubkeys:output_type -> orlyacl.v1.FollowedPubkeysResponse + 30, // 53: orlyacl.v1.ACLService.GetAdminRelays:output_type -> orlyacl.v1.AdminRelaysResponse + 2, // 54: orlyacl.v1.ACLService.BanPubkey:output_type -> orlyacl.v1.Empty + 2, // 55: orlyacl.v1.ACLService.UnbanPubkey:output_type -> orlyacl.v1.Empty + 31, // 56: orlyacl.v1.ACLService.ListBannedPubkeys:output_type -> orlyacl.v1.ListBannedPubkeysResponse + 2, // 57: orlyacl.v1.ACLService.AllowPubkey:output_type -> orlyacl.v1.Empty + 2, // 58: orlyacl.v1.ACLService.DisallowPubkey:output_type -> orlyacl.v1.Empty + 32, // 59: orlyacl.v1.ACLService.ListAllowedPubkeys:output_type -> orlyacl.v1.ListAllowedPubkeysResponse + 2, // 60: orlyacl.v1.ACLService.BanEvent:output_type -> orlyacl.v1.Empty + 2, // 61: orlyacl.v1.ACLService.UnbanEvent:output_type -> orlyacl.v1.Empty + 33, // 62: orlyacl.v1.ACLService.ListBannedEvents:output_type -> orlyacl.v1.ListBannedEventsResponse + 2, // 63: orlyacl.v1.ACLService.AllowEvent:output_type -> orlyacl.v1.Empty + 2, // 64: orlyacl.v1.ACLService.DisallowEvent:output_type -> orlyacl.v1.Empty + 34, // 65: orlyacl.v1.ACLService.ListAllowedEvents:output_type -> orlyacl.v1.ListAllowedEventsResponse + 2, // 66: orlyacl.v1.ACLService.BlockIP:output_type -> orlyacl.v1.Empty + 2, // 67: orlyacl.v1.ACLService.UnblockIP:output_type -> orlyacl.v1.Empty + 35, // 68: orlyacl.v1.ACLService.ListBlockedIPs:output_type -> orlyacl.v1.ListBlockedIPsResponse + 2, // 69: orlyacl.v1.ACLService.AllowKind:output_type -> orlyacl.v1.Empty + 2, // 70: orlyacl.v1.ACLService.DisallowKind:output_type -> orlyacl.v1.Empty + 36, // 71: orlyacl.v1.ACLService.ListAllowedKinds:output_type -> orlyacl.v1.ListAllowedKindsResponse + 2, // 72: orlyacl.v1.ACLService.UpdatePeerAdmins:output_type -> orlyacl.v1.Empty + 2, // 73: orlyacl.v1.ACLService.TrustPubkey:output_type -> orlyacl.v1.Empty + 2, // 74: orlyacl.v1.ACLService.UntrustPubkey:output_type -> orlyacl.v1.Empty + 37, // 75: orlyacl.v1.ACLService.ListTrustedPubkeys:output_type -> orlyacl.v1.ListTrustedPubkeysResponse + 2, // 76: orlyacl.v1.ACLService.BlacklistPubkey:output_type -> orlyacl.v1.Empty + 2, // 77: orlyacl.v1.ACLService.UnblacklistPubkey:output_type -> orlyacl.v1.Empty + 38, // 78: orlyacl.v1.ACLService.ListBlacklistedPubkeys:output_type -> orlyacl.v1.ListBlacklistedPubkeysResponse + 2, // 79: orlyacl.v1.ACLService.MarkSpam:output_type -> orlyacl.v1.Empty + 2, // 80: orlyacl.v1.ACLService.UnmarkSpam:output_type -> orlyacl.v1.Empty + 39, // 81: orlyacl.v1.ACLService.ListSpamEvents:output_type -> orlyacl.v1.ListSpamEventsResponse + 40, // 82: orlyacl.v1.ACLService.RateLimitCheck:output_type -> orlyacl.v1.RateLimitCheckResponse + 2, // 83: orlyacl.v1.ACLService.ProcessConfigEvent:output_type -> orlyacl.v1.Empty + 41, // 84: orlyacl.v1.ACLService.GetCuratingConfig:output_type -> orlyacl.v1.CuratingConfig + 42, // 85: orlyacl.v1.ACLService.IsCuratingConfigured:output_type -> orlyacl.v1.BoolResponse + 43, // 86: orlyacl.v1.ACLService.ListUnclassifiedUsers:output_type -> orlyacl.v1.ListUnclassifiedUsersResponse + 44, // 87: orlyacl.v1.ACLService.GetEventsForPubkey:output_type -> orlyacl.v1.EventsForPubkeyResponse + 45, // 88: orlyacl.v1.ACLService.DeleteEventsForPubkey:output_type -> orlyacl.v1.DeleteCountResponse + 46, // 89: orlyacl.v1.ACLService.ScanAllPubkeys:output_type -> orlyacl.v1.ScanResultResponse + 45, // [45:90] is the sub-list for method output_type + 0, // [0:45] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_orlyacl_v1_acl_proto_init() } +func file_orlyacl_v1_acl_proto_init() { + if File_orlyacl_v1_acl_proto != nil { + return + } + file_orlyacl_v1_types_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_orlyacl_v1_acl_proto_rawDesc), len(file_orlyacl_v1_acl_proto_rawDesc)), + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_orlyacl_v1_acl_proto_goTypes, + DependencyIndexes: file_orlyacl_v1_acl_proto_depIdxs, + }.Build() + File_orlyacl_v1_acl_proto = out.File + file_orlyacl_v1_acl_proto_goTypes = nil + file_orlyacl_v1_acl_proto_depIdxs = nil +} diff --git a/pkg/proto/orlyacl/v1/acl_grpc.pb.go b/pkg/proto/orlyacl/v1/acl_grpc.pb.go new file mode 100644 index 0000000..26e7845 --- /dev/null +++ b/pkg/proto/orlyacl/v1/acl_grpc.pb.go @@ -0,0 +1,1887 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.0 +// - protoc (unknown) +// source: orlyacl/v1/acl.proto + +package orlyaclv1 + +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.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ACLService_GetAccessLevel_FullMethodName = "/orlyacl.v1.ACLService/GetAccessLevel" + ACLService_CheckPolicy_FullMethodName = "/orlyacl.v1.ACLService/CheckPolicy" + ACLService_GetACLInfo_FullMethodName = "/orlyacl.v1.ACLService/GetACLInfo" + ACLService_GetMode_FullMethodName = "/orlyacl.v1.ACLService/GetMode" + ACLService_Ready_FullMethodName = "/orlyacl.v1.ACLService/Ready" + ACLService_GetThrottleDelay_FullMethodName = "/orlyacl.v1.ACLService/GetThrottleDelay" + ACLService_AddFollow_FullMethodName = "/orlyacl.v1.ACLService/AddFollow" + ACLService_GetFollowedPubkeys_FullMethodName = "/orlyacl.v1.ACLService/GetFollowedPubkeys" + ACLService_GetAdminRelays_FullMethodName = "/orlyacl.v1.ACLService/GetAdminRelays" + ACLService_BanPubkey_FullMethodName = "/orlyacl.v1.ACLService/BanPubkey" + ACLService_UnbanPubkey_FullMethodName = "/orlyacl.v1.ACLService/UnbanPubkey" + ACLService_ListBannedPubkeys_FullMethodName = "/orlyacl.v1.ACLService/ListBannedPubkeys" + ACLService_AllowPubkey_FullMethodName = "/orlyacl.v1.ACLService/AllowPubkey" + ACLService_DisallowPubkey_FullMethodName = "/orlyacl.v1.ACLService/DisallowPubkey" + ACLService_ListAllowedPubkeys_FullMethodName = "/orlyacl.v1.ACLService/ListAllowedPubkeys" + ACLService_BanEvent_FullMethodName = "/orlyacl.v1.ACLService/BanEvent" + ACLService_UnbanEvent_FullMethodName = "/orlyacl.v1.ACLService/UnbanEvent" + ACLService_ListBannedEvents_FullMethodName = "/orlyacl.v1.ACLService/ListBannedEvents" + ACLService_AllowEvent_FullMethodName = "/orlyacl.v1.ACLService/AllowEvent" + ACLService_DisallowEvent_FullMethodName = "/orlyacl.v1.ACLService/DisallowEvent" + ACLService_ListAllowedEvents_FullMethodName = "/orlyacl.v1.ACLService/ListAllowedEvents" + ACLService_BlockIP_FullMethodName = "/orlyacl.v1.ACLService/BlockIP" + ACLService_UnblockIP_FullMethodName = "/orlyacl.v1.ACLService/UnblockIP" + ACLService_ListBlockedIPs_FullMethodName = "/orlyacl.v1.ACLService/ListBlockedIPs" + ACLService_AllowKind_FullMethodName = "/orlyacl.v1.ACLService/AllowKind" + ACLService_DisallowKind_FullMethodName = "/orlyacl.v1.ACLService/DisallowKind" + ACLService_ListAllowedKinds_FullMethodName = "/orlyacl.v1.ACLService/ListAllowedKinds" + ACLService_UpdatePeerAdmins_FullMethodName = "/orlyacl.v1.ACLService/UpdatePeerAdmins" + ACLService_TrustPubkey_FullMethodName = "/orlyacl.v1.ACLService/TrustPubkey" + ACLService_UntrustPubkey_FullMethodName = "/orlyacl.v1.ACLService/UntrustPubkey" + ACLService_ListTrustedPubkeys_FullMethodName = "/orlyacl.v1.ACLService/ListTrustedPubkeys" + ACLService_BlacklistPubkey_FullMethodName = "/orlyacl.v1.ACLService/BlacklistPubkey" + ACLService_UnblacklistPubkey_FullMethodName = "/orlyacl.v1.ACLService/UnblacklistPubkey" + ACLService_ListBlacklistedPubkeys_FullMethodName = "/orlyacl.v1.ACLService/ListBlacklistedPubkeys" + ACLService_MarkSpam_FullMethodName = "/orlyacl.v1.ACLService/MarkSpam" + ACLService_UnmarkSpam_FullMethodName = "/orlyacl.v1.ACLService/UnmarkSpam" + ACLService_ListSpamEvents_FullMethodName = "/orlyacl.v1.ACLService/ListSpamEvents" + ACLService_RateLimitCheck_FullMethodName = "/orlyacl.v1.ACLService/RateLimitCheck" + ACLService_ProcessConfigEvent_FullMethodName = "/orlyacl.v1.ACLService/ProcessConfigEvent" + ACLService_GetCuratingConfig_FullMethodName = "/orlyacl.v1.ACLService/GetCuratingConfig" + ACLService_IsCuratingConfigured_FullMethodName = "/orlyacl.v1.ACLService/IsCuratingConfigured" + ACLService_ListUnclassifiedUsers_FullMethodName = "/orlyacl.v1.ACLService/ListUnclassifiedUsers" + ACLService_GetEventsForPubkey_FullMethodName = "/orlyacl.v1.ACLService/GetEventsForPubkey" + ACLService_DeleteEventsForPubkey_FullMethodName = "/orlyacl.v1.ACLService/DeleteEventsForPubkey" + ACLService_ScanAllPubkeys_FullMethodName = "/orlyacl.v1.ACLService/ScanAllPubkeys" +) + +// ACLServiceClient is the client API for ACLService 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. +// +// ACLService provides access control operations for the Nostr relay +type ACLServiceClient interface { + // GetAccessLevel returns the access level for a pubkey from an IP address + GetAccessLevel(ctx context.Context, in *AccessLevelRequest, opts ...grpc.CallOption) (*AccessLevelResponse, error) + // CheckPolicy checks if an event passes policy checks + CheckPolicy(ctx context.Context, in *PolicyCheckRequest, opts ...grpc.CallOption) (*PolicyCheckResponse, error) + // GetACLInfo returns information about the active ACL mode + GetACLInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ACLInfoResponse, error) + // GetMode returns the current ACL mode (none/follows/managed/curating) + GetMode(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ModeResponse, error) + // Ready checks if the ACL service is ready + Ready(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReadyResponse, error) + // GetThrottleDelay returns the progressive throttle delay for a pubkey + GetThrottleDelay(ctx context.Context, in *ThrottleDelayRequest, opts ...grpc.CallOption) (*ThrottleDelayResponse, error) + // AddFollow adds a pubkey to the followed list + AddFollow(ctx context.Context, in *AddFollowRequest, opts ...grpc.CallOption) (*Empty, error) + // GetFollowedPubkeys returns all followed pubkeys + GetFollowedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*FollowedPubkeysResponse, error) + // GetAdminRelays returns the relay URLs from admin kind 10002 events + GetAdminRelays(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AdminRelaysResponse, error) + // BanPubkey adds a pubkey to the ban list + BanPubkey(ctx context.Context, in *BanPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // UnbanPubkey removes a pubkey from the ban list + UnbanPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // ListBannedPubkeys returns all banned pubkeys + ListBannedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBannedPubkeysResponse, error) + // AllowPubkey adds a pubkey to the allow list + AllowPubkey(ctx context.Context, in *AllowPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // DisallowPubkey removes a pubkey from the allow list + DisallowPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // ListAllowedPubkeys returns all explicitly allowed pubkeys + ListAllowedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedPubkeysResponse, error) + // BanEvent adds an event to the ban list + BanEvent(ctx context.Context, in *BanEventRequest, opts ...grpc.CallOption) (*Empty, error) + // UnbanEvent removes an event from the ban list + UnbanEvent(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) + // ListBannedEvents returns all banned events + ListBannedEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBannedEventsResponse, error) + // AllowEvent adds an event to the allow list + AllowEvent(ctx context.Context, in *BanEventRequest, opts ...grpc.CallOption) (*Empty, error) + // DisallowEvent removes an event from the allow list + DisallowEvent(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) + // ListAllowedEvents returns all explicitly allowed events + ListAllowedEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedEventsResponse, error) + // BlockIP adds an IP to the block list + BlockIP(ctx context.Context, in *BlockIPRequest, opts ...grpc.CallOption) (*Empty, error) + // UnblockIP removes an IP from the block list + UnblockIP(ctx context.Context, in *IPRequest, opts ...grpc.CallOption) (*Empty, error) + // ListBlockedIPs returns all blocked IPs + ListBlockedIPs(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBlockedIPsResponse, error) + // AllowKind adds a kind to the allow list + AllowKind(ctx context.Context, in *AllowKindRequest, opts ...grpc.CallOption) (*Empty, error) + // DisallowKind removes a kind from the allow list + DisallowKind(ctx context.Context, in *KindRequest, opts ...grpc.CallOption) (*Empty, error) + // ListAllowedKinds returns all allowed kinds + ListAllowedKinds(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedKindsResponse, error) + // UpdatePeerAdmins updates the peer relay identity pubkeys + UpdatePeerAdmins(ctx context.Context, in *UpdatePeerAdminsRequest, opts ...grpc.CallOption) (*Empty, error) + // TrustPubkey adds a pubkey to the trusted list + TrustPubkey(ctx context.Context, in *TrustPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // UntrustPubkey removes a pubkey from the trusted list + UntrustPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // ListTrustedPubkeys returns all trusted pubkeys + ListTrustedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListTrustedPubkeysResponse, error) + // BlacklistPubkey adds a pubkey to the blacklist + BlacklistPubkey(ctx context.Context, in *BlacklistPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // UnblacklistPubkey removes a pubkey from the blacklist + UnblacklistPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) + // ListBlacklistedPubkeys returns all blacklisted pubkeys + ListBlacklistedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBlacklistedPubkeysResponse, error) + // MarkSpam marks an event as spam + MarkSpam(ctx context.Context, in *MarkSpamRequest, opts ...grpc.CallOption) (*Empty, error) + // UnmarkSpam removes the spam flag from an event + UnmarkSpam(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) + // ListSpamEvents returns all spam-flagged events + ListSpamEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListSpamEventsResponse, error) + // RateLimitCheck checks if a pubkey/IP can publish (rate limiting) + RateLimitCheck(ctx context.Context, in *RateLimitCheckRequest, opts ...grpc.CallOption) (*RateLimitCheckResponse, error) + // ProcessConfigEvent processes a curating config event (kind 30078) + ProcessConfigEvent(ctx context.Context, in *ConfigEventRequest, opts ...grpc.CallOption) (*Empty, error) + // GetCuratingConfig returns the current curating configuration + GetCuratingConfig(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CuratingConfig, error) + // IsCuratingConfigured checks if curating mode is configured + IsCuratingConfigured(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BoolResponse, error) + // ListUnclassifiedUsers returns users who are not trusted or blacklisted + ListUnclassifiedUsers(ctx context.Context, in *PaginationRequest, opts ...grpc.CallOption) (*ListUnclassifiedUsersResponse, error) + // GetEventsForPubkey returns events for a specific pubkey + GetEventsForPubkey(ctx context.Context, in *GetEventsForPubkeyRequest, opts ...grpc.CallOption) (*EventsForPubkeyResponse, error) + // DeleteEventsForPubkey deletes all events for a pubkey + DeleteEventsForPubkey(ctx context.Context, in *DeleteEventsForPubkeyRequest, opts ...grpc.CallOption) (*DeleteCountResponse, error) + // ScanAllPubkeys scans and indexes all pubkeys in the database + ScanAllPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ScanResultResponse, error) +} + +type aCLServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewACLServiceClient(cc grpc.ClientConnInterface) ACLServiceClient { + return &aCLServiceClient{cc} +} + +func (c *aCLServiceClient) GetAccessLevel(ctx context.Context, in *AccessLevelRequest, opts ...grpc.CallOption) (*AccessLevelResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AccessLevelResponse) + err := c.cc.Invoke(ctx, ACLService_GetAccessLevel_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) CheckPolicy(ctx context.Context, in *PolicyCheckRequest, opts ...grpc.CallOption) (*PolicyCheckResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PolicyCheckResponse) + err := c.cc.Invoke(ctx, ACLService_CheckPolicy_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetACLInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ACLInfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ACLInfoResponse) + err := c.cc.Invoke(ctx, ACLService_GetACLInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetMode(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ModeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ModeResponse) + err := c.cc.Invoke(ctx, ACLService_GetMode_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) Ready(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ReadyResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ReadyResponse) + err := c.cc.Invoke(ctx, ACLService_Ready_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetThrottleDelay(ctx context.Context, in *ThrottleDelayRequest, opts ...grpc.CallOption) (*ThrottleDelayResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ThrottleDelayResponse) + err := c.cc.Invoke(ctx, ACLService_GetThrottleDelay_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) AddFollow(ctx context.Context, in *AddFollowRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_AddFollow_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetFollowedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*FollowedPubkeysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FollowedPubkeysResponse) + err := c.cc.Invoke(ctx, ACLService_GetFollowedPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetAdminRelays(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AdminRelaysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AdminRelaysResponse) + err := c.cc.Invoke(ctx, ACLService_GetAdminRelays_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) BanPubkey(ctx context.Context, in *BanPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_BanPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UnbanPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UnbanPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListBannedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBannedPubkeysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBannedPubkeysResponse) + err := c.cc.Invoke(ctx, ACLService_ListBannedPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) AllowPubkey(ctx context.Context, in *AllowPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_AllowPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) DisallowPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_DisallowPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListAllowedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedPubkeysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListAllowedPubkeysResponse) + err := c.cc.Invoke(ctx, ACLService_ListAllowedPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) BanEvent(ctx context.Context, in *BanEventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_BanEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UnbanEvent(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UnbanEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListBannedEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBannedEventsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBannedEventsResponse) + err := c.cc.Invoke(ctx, ACLService_ListBannedEvents_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) AllowEvent(ctx context.Context, in *BanEventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_AllowEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) DisallowEvent(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_DisallowEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListAllowedEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedEventsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListAllowedEventsResponse) + err := c.cc.Invoke(ctx, ACLService_ListAllowedEvents_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) BlockIP(ctx context.Context, in *BlockIPRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_BlockIP_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UnblockIP(ctx context.Context, in *IPRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UnblockIP_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListBlockedIPs(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBlockedIPsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBlockedIPsResponse) + err := c.cc.Invoke(ctx, ACLService_ListBlockedIPs_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) AllowKind(ctx context.Context, in *AllowKindRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_AllowKind_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) DisallowKind(ctx context.Context, in *KindRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_DisallowKind_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListAllowedKinds(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListAllowedKindsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListAllowedKindsResponse) + err := c.cc.Invoke(ctx, ACLService_ListAllowedKinds_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UpdatePeerAdmins(ctx context.Context, in *UpdatePeerAdminsRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UpdatePeerAdmins_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) TrustPubkey(ctx context.Context, in *TrustPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_TrustPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UntrustPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UntrustPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListTrustedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListTrustedPubkeysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListTrustedPubkeysResponse) + err := c.cc.Invoke(ctx, ACLService_ListTrustedPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) BlacklistPubkey(ctx context.Context, in *BlacklistPubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_BlacklistPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UnblacklistPubkey(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UnblacklistPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListBlacklistedPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListBlacklistedPubkeysResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBlacklistedPubkeysResponse) + err := c.cc.Invoke(ctx, ACLService_ListBlacklistedPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) MarkSpam(ctx context.Context, in *MarkSpamRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_MarkSpam_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) UnmarkSpam(ctx context.Context, in *EventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_UnmarkSpam_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListSpamEvents(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListSpamEventsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListSpamEventsResponse) + err := c.cc.Invoke(ctx, ACLService_ListSpamEvents_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) RateLimitCheck(ctx context.Context, in *RateLimitCheckRequest, opts ...grpc.CallOption) (*RateLimitCheckResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RateLimitCheckResponse) + err := c.cc.Invoke(ctx, ACLService_RateLimitCheck_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ProcessConfigEvent(ctx context.Context, in *ConfigEventRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, ACLService_ProcessConfigEvent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetCuratingConfig(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CuratingConfig, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CuratingConfig) + err := c.cc.Invoke(ctx, ACLService_GetCuratingConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) IsCuratingConfigured(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BoolResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BoolResponse) + err := c.cc.Invoke(ctx, ACLService_IsCuratingConfigured_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ListUnclassifiedUsers(ctx context.Context, in *PaginationRequest, opts ...grpc.CallOption) (*ListUnclassifiedUsersResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListUnclassifiedUsersResponse) + err := c.cc.Invoke(ctx, ACLService_ListUnclassifiedUsers_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) GetEventsForPubkey(ctx context.Context, in *GetEventsForPubkeyRequest, opts ...grpc.CallOption) (*EventsForPubkeyResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(EventsForPubkeyResponse) + err := c.cc.Invoke(ctx, ACLService_GetEventsForPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) DeleteEventsForPubkey(ctx context.Context, in *DeleteEventsForPubkeyRequest, opts ...grpc.CallOption) (*DeleteCountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteCountResponse) + err := c.cc.Invoke(ctx, ACLService_DeleteEventsForPubkey_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aCLServiceClient) ScanAllPubkeys(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ScanResultResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ScanResultResponse) + err := c.cc.Invoke(ctx, ACLService_ScanAllPubkeys_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ACLServiceServer is the server API for ACLService service. +// All implementations must embed UnimplementedACLServiceServer +// for forward compatibility. +// +// ACLService provides access control operations for the Nostr relay +type ACLServiceServer interface { + // GetAccessLevel returns the access level for a pubkey from an IP address + GetAccessLevel(context.Context, *AccessLevelRequest) (*AccessLevelResponse, error) + // CheckPolicy checks if an event passes policy checks + CheckPolicy(context.Context, *PolicyCheckRequest) (*PolicyCheckResponse, error) + // GetACLInfo returns information about the active ACL mode + GetACLInfo(context.Context, *Empty) (*ACLInfoResponse, error) + // GetMode returns the current ACL mode (none/follows/managed/curating) + GetMode(context.Context, *Empty) (*ModeResponse, error) + // Ready checks if the ACL service is ready + Ready(context.Context, *Empty) (*ReadyResponse, error) + // GetThrottleDelay returns the progressive throttle delay for a pubkey + GetThrottleDelay(context.Context, *ThrottleDelayRequest) (*ThrottleDelayResponse, error) + // AddFollow adds a pubkey to the followed list + AddFollow(context.Context, *AddFollowRequest) (*Empty, error) + // GetFollowedPubkeys returns all followed pubkeys + GetFollowedPubkeys(context.Context, *Empty) (*FollowedPubkeysResponse, error) + // GetAdminRelays returns the relay URLs from admin kind 10002 events + GetAdminRelays(context.Context, *Empty) (*AdminRelaysResponse, error) + // BanPubkey adds a pubkey to the ban list + BanPubkey(context.Context, *BanPubkeyRequest) (*Empty, error) + // UnbanPubkey removes a pubkey from the ban list + UnbanPubkey(context.Context, *PubkeyRequest) (*Empty, error) + // ListBannedPubkeys returns all banned pubkeys + ListBannedPubkeys(context.Context, *Empty) (*ListBannedPubkeysResponse, error) + // AllowPubkey adds a pubkey to the allow list + AllowPubkey(context.Context, *AllowPubkeyRequest) (*Empty, error) + // DisallowPubkey removes a pubkey from the allow list + DisallowPubkey(context.Context, *PubkeyRequest) (*Empty, error) + // ListAllowedPubkeys returns all explicitly allowed pubkeys + ListAllowedPubkeys(context.Context, *Empty) (*ListAllowedPubkeysResponse, error) + // BanEvent adds an event to the ban list + BanEvent(context.Context, *BanEventRequest) (*Empty, error) + // UnbanEvent removes an event from the ban list + UnbanEvent(context.Context, *EventRequest) (*Empty, error) + // ListBannedEvents returns all banned events + ListBannedEvents(context.Context, *Empty) (*ListBannedEventsResponse, error) + // AllowEvent adds an event to the allow list + AllowEvent(context.Context, *BanEventRequest) (*Empty, error) + // DisallowEvent removes an event from the allow list + DisallowEvent(context.Context, *EventRequest) (*Empty, error) + // ListAllowedEvents returns all explicitly allowed events + ListAllowedEvents(context.Context, *Empty) (*ListAllowedEventsResponse, error) + // BlockIP adds an IP to the block list + BlockIP(context.Context, *BlockIPRequest) (*Empty, error) + // UnblockIP removes an IP from the block list + UnblockIP(context.Context, *IPRequest) (*Empty, error) + // ListBlockedIPs returns all blocked IPs + ListBlockedIPs(context.Context, *Empty) (*ListBlockedIPsResponse, error) + // AllowKind adds a kind to the allow list + AllowKind(context.Context, *AllowKindRequest) (*Empty, error) + // DisallowKind removes a kind from the allow list + DisallowKind(context.Context, *KindRequest) (*Empty, error) + // ListAllowedKinds returns all allowed kinds + ListAllowedKinds(context.Context, *Empty) (*ListAllowedKindsResponse, error) + // UpdatePeerAdmins updates the peer relay identity pubkeys + UpdatePeerAdmins(context.Context, *UpdatePeerAdminsRequest) (*Empty, error) + // TrustPubkey adds a pubkey to the trusted list + TrustPubkey(context.Context, *TrustPubkeyRequest) (*Empty, error) + // UntrustPubkey removes a pubkey from the trusted list + UntrustPubkey(context.Context, *PubkeyRequest) (*Empty, error) + // ListTrustedPubkeys returns all trusted pubkeys + ListTrustedPubkeys(context.Context, *Empty) (*ListTrustedPubkeysResponse, error) + // BlacklistPubkey adds a pubkey to the blacklist + BlacklistPubkey(context.Context, *BlacklistPubkeyRequest) (*Empty, error) + // UnblacklistPubkey removes a pubkey from the blacklist + UnblacklistPubkey(context.Context, *PubkeyRequest) (*Empty, error) + // ListBlacklistedPubkeys returns all blacklisted pubkeys + ListBlacklistedPubkeys(context.Context, *Empty) (*ListBlacklistedPubkeysResponse, error) + // MarkSpam marks an event as spam + MarkSpam(context.Context, *MarkSpamRequest) (*Empty, error) + // UnmarkSpam removes the spam flag from an event + UnmarkSpam(context.Context, *EventRequest) (*Empty, error) + // ListSpamEvents returns all spam-flagged events + ListSpamEvents(context.Context, *Empty) (*ListSpamEventsResponse, error) + // RateLimitCheck checks if a pubkey/IP can publish (rate limiting) + RateLimitCheck(context.Context, *RateLimitCheckRequest) (*RateLimitCheckResponse, error) + // ProcessConfigEvent processes a curating config event (kind 30078) + ProcessConfigEvent(context.Context, *ConfigEventRequest) (*Empty, error) + // GetCuratingConfig returns the current curating configuration + GetCuratingConfig(context.Context, *Empty) (*CuratingConfig, error) + // IsCuratingConfigured checks if curating mode is configured + IsCuratingConfigured(context.Context, *Empty) (*BoolResponse, error) + // ListUnclassifiedUsers returns users who are not trusted or blacklisted + ListUnclassifiedUsers(context.Context, *PaginationRequest) (*ListUnclassifiedUsersResponse, error) + // GetEventsForPubkey returns events for a specific pubkey + GetEventsForPubkey(context.Context, *GetEventsForPubkeyRequest) (*EventsForPubkeyResponse, error) + // DeleteEventsForPubkey deletes all events for a pubkey + DeleteEventsForPubkey(context.Context, *DeleteEventsForPubkeyRequest) (*DeleteCountResponse, error) + // ScanAllPubkeys scans and indexes all pubkeys in the database + ScanAllPubkeys(context.Context, *Empty) (*ScanResultResponse, error) + mustEmbedUnimplementedACLServiceServer() +} + +// UnimplementedACLServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedACLServiceServer struct{} + +func (UnimplementedACLServiceServer) GetAccessLevel(context.Context, *AccessLevelRequest) (*AccessLevelResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetAccessLevel not implemented") +} +func (UnimplementedACLServiceServer) CheckPolicy(context.Context, *PolicyCheckRequest) (*PolicyCheckResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CheckPolicy not implemented") +} +func (UnimplementedACLServiceServer) GetACLInfo(context.Context, *Empty) (*ACLInfoResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetACLInfo not implemented") +} +func (UnimplementedACLServiceServer) GetMode(context.Context, *Empty) (*ModeResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetMode not implemented") +} +func (UnimplementedACLServiceServer) Ready(context.Context, *Empty) (*ReadyResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Ready not implemented") +} +func (UnimplementedACLServiceServer) GetThrottleDelay(context.Context, *ThrottleDelayRequest) (*ThrottleDelayResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetThrottleDelay not implemented") +} +func (UnimplementedACLServiceServer) AddFollow(context.Context, *AddFollowRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method AddFollow not implemented") +} +func (UnimplementedACLServiceServer) GetFollowedPubkeys(context.Context, *Empty) (*FollowedPubkeysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetFollowedPubkeys not implemented") +} +func (UnimplementedACLServiceServer) GetAdminRelays(context.Context, *Empty) (*AdminRelaysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetAdminRelays not implemented") +} +func (UnimplementedACLServiceServer) BanPubkey(context.Context, *BanPubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method BanPubkey not implemented") +} +func (UnimplementedACLServiceServer) UnbanPubkey(context.Context, *PubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UnbanPubkey not implemented") +} +func (UnimplementedACLServiceServer) ListBannedPubkeys(context.Context, *Empty) (*ListBannedPubkeysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBannedPubkeys not implemented") +} +func (UnimplementedACLServiceServer) AllowPubkey(context.Context, *AllowPubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method AllowPubkey not implemented") +} +func (UnimplementedACLServiceServer) DisallowPubkey(context.Context, *PubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DisallowPubkey not implemented") +} +func (UnimplementedACLServiceServer) ListAllowedPubkeys(context.Context, *Empty) (*ListAllowedPubkeysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListAllowedPubkeys not implemented") +} +func (UnimplementedACLServiceServer) BanEvent(context.Context, *BanEventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method BanEvent not implemented") +} +func (UnimplementedACLServiceServer) UnbanEvent(context.Context, *EventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UnbanEvent not implemented") +} +func (UnimplementedACLServiceServer) ListBannedEvents(context.Context, *Empty) (*ListBannedEventsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBannedEvents not implemented") +} +func (UnimplementedACLServiceServer) AllowEvent(context.Context, *BanEventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method AllowEvent not implemented") +} +func (UnimplementedACLServiceServer) DisallowEvent(context.Context, *EventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DisallowEvent not implemented") +} +func (UnimplementedACLServiceServer) ListAllowedEvents(context.Context, *Empty) (*ListAllowedEventsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListAllowedEvents not implemented") +} +func (UnimplementedACLServiceServer) BlockIP(context.Context, *BlockIPRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method BlockIP not implemented") +} +func (UnimplementedACLServiceServer) UnblockIP(context.Context, *IPRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UnblockIP not implemented") +} +func (UnimplementedACLServiceServer) ListBlockedIPs(context.Context, *Empty) (*ListBlockedIPsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBlockedIPs not implemented") +} +func (UnimplementedACLServiceServer) AllowKind(context.Context, *AllowKindRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method AllowKind not implemented") +} +func (UnimplementedACLServiceServer) DisallowKind(context.Context, *KindRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method DisallowKind not implemented") +} +func (UnimplementedACLServiceServer) ListAllowedKinds(context.Context, *Empty) (*ListAllowedKindsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListAllowedKinds not implemented") +} +func (UnimplementedACLServiceServer) UpdatePeerAdmins(context.Context, *UpdatePeerAdminsRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UpdatePeerAdmins not implemented") +} +func (UnimplementedACLServiceServer) TrustPubkey(context.Context, *TrustPubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method TrustPubkey not implemented") +} +func (UnimplementedACLServiceServer) UntrustPubkey(context.Context, *PubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UntrustPubkey not implemented") +} +func (UnimplementedACLServiceServer) ListTrustedPubkeys(context.Context, *Empty) (*ListTrustedPubkeysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListTrustedPubkeys not implemented") +} +func (UnimplementedACLServiceServer) BlacklistPubkey(context.Context, *BlacklistPubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method BlacklistPubkey not implemented") +} +func (UnimplementedACLServiceServer) UnblacklistPubkey(context.Context, *PubkeyRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UnblacklistPubkey not implemented") +} +func (UnimplementedACLServiceServer) ListBlacklistedPubkeys(context.Context, *Empty) (*ListBlacklistedPubkeysResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBlacklistedPubkeys not implemented") +} +func (UnimplementedACLServiceServer) MarkSpam(context.Context, *MarkSpamRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method MarkSpam not implemented") +} +func (UnimplementedACLServiceServer) UnmarkSpam(context.Context, *EventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method UnmarkSpam not implemented") +} +func (UnimplementedACLServiceServer) ListSpamEvents(context.Context, *Empty) (*ListSpamEventsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListSpamEvents not implemented") +} +func (UnimplementedACLServiceServer) RateLimitCheck(context.Context, *RateLimitCheckRequest) (*RateLimitCheckResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RateLimitCheck not implemented") +} +func (UnimplementedACLServiceServer) ProcessConfigEvent(context.Context, *ConfigEventRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method ProcessConfigEvent not implemented") +} +func (UnimplementedACLServiceServer) GetCuratingConfig(context.Context, *Empty) (*CuratingConfig, error) { + return nil, status.Error(codes.Unimplemented, "method GetCuratingConfig not implemented") +} +func (UnimplementedACLServiceServer) IsCuratingConfigured(context.Context, *Empty) (*BoolResponse, error) { + return nil, status.Error(codes.Unimplemented, "method IsCuratingConfigured not implemented") +} +func (UnimplementedACLServiceServer) ListUnclassifiedUsers(context.Context, *PaginationRequest) (*ListUnclassifiedUsersResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListUnclassifiedUsers not implemented") +} +func (UnimplementedACLServiceServer) GetEventsForPubkey(context.Context, *GetEventsForPubkeyRequest) (*EventsForPubkeyResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetEventsForPubkey not implemented") +} +func (UnimplementedACLServiceServer) DeleteEventsForPubkey(context.Context, *DeleteEventsForPubkeyRequest) (*DeleteCountResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteEventsForPubkey not implemented") +} +func (UnimplementedACLServiceServer) ScanAllPubkeys(context.Context, *Empty) (*ScanResultResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ScanAllPubkeys not implemented") +} +func (UnimplementedACLServiceServer) mustEmbedUnimplementedACLServiceServer() {} +func (UnimplementedACLServiceServer) testEmbeddedByValue() {} + +// UnsafeACLServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ACLServiceServer will +// result in compilation errors. +type UnsafeACLServiceServer interface { + mustEmbedUnimplementedACLServiceServer() +} + +func RegisterACLServiceServer(s grpc.ServiceRegistrar, srv ACLServiceServer) { + // If the following call panics, it indicates UnimplementedACLServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ACLService_ServiceDesc, srv) +} + +func _ACLService_GetAccessLevel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AccessLevelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetAccessLevel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetAccessLevel_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetAccessLevel(ctx, req.(*AccessLevelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_CheckPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PolicyCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).CheckPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_CheckPolicy_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).CheckPolicy(ctx, req.(*PolicyCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetACLInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetACLInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetACLInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetACLInfo(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetMode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetMode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetMode_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetMode(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_Ready_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).Ready(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_Ready_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).Ready(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetThrottleDelay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ThrottleDelayRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetThrottleDelay(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetThrottleDelay_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetThrottleDelay(ctx, req.(*ThrottleDelayRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_AddFollow_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddFollowRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).AddFollow(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_AddFollow_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).AddFollow(ctx, req.(*AddFollowRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetFollowedPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetFollowedPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetFollowedPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetFollowedPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetAdminRelays_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetAdminRelays(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetAdminRelays_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetAdminRelays(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_BanPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BanPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).BanPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_BanPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).BanPubkey(ctx, req.(*BanPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UnbanPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UnbanPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UnbanPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UnbanPubkey(ctx, req.(*PubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListBannedPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListBannedPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListBannedPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListBannedPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_AllowPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AllowPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).AllowPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_AllowPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).AllowPubkey(ctx, req.(*AllowPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_DisallowPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).DisallowPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_DisallowPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).DisallowPubkey(ctx, req.(*PubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListAllowedPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListAllowedPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListAllowedPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListAllowedPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_BanEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BanEventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).BanEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_BanEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).BanEvent(ctx, req.(*BanEventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UnbanEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UnbanEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UnbanEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UnbanEvent(ctx, req.(*EventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListBannedEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListBannedEvents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListBannedEvents_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListBannedEvents(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_AllowEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BanEventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).AllowEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_AllowEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).AllowEvent(ctx, req.(*BanEventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_DisallowEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).DisallowEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_DisallowEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).DisallowEvent(ctx, req.(*EventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListAllowedEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListAllowedEvents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListAllowedEvents_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListAllowedEvents(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_BlockIP_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BlockIPRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).BlockIP(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_BlockIP_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).BlockIP(ctx, req.(*BlockIPRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UnblockIP_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IPRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UnblockIP(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UnblockIP_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UnblockIP(ctx, req.(*IPRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListBlockedIPs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListBlockedIPs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListBlockedIPs_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListBlockedIPs(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_AllowKind_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AllowKindRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).AllowKind(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_AllowKind_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).AllowKind(ctx, req.(*AllowKindRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_DisallowKind_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KindRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).DisallowKind(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_DisallowKind_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).DisallowKind(ctx, req.(*KindRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListAllowedKinds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListAllowedKinds(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListAllowedKinds_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListAllowedKinds(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UpdatePeerAdmins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePeerAdminsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UpdatePeerAdmins(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UpdatePeerAdmins_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UpdatePeerAdmins(ctx, req.(*UpdatePeerAdminsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_TrustPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TrustPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).TrustPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_TrustPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).TrustPubkey(ctx, req.(*TrustPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UntrustPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UntrustPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UntrustPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UntrustPubkey(ctx, req.(*PubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListTrustedPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListTrustedPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListTrustedPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListTrustedPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_BlacklistPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BlacklistPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).BlacklistPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_BlacklistPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).BlacklistPubkey(ctx, req.(*BlacklistPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UnblacklistPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UnblacklistPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UnblacklistPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UnblacklistPubkey(ctx, req.(*PubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListBlacklistedPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListBlacklistedPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListBlacklistedPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListBlacklistedPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_MarkSpam_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MarkSpamRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).MarkSpam(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_MarkSpam_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).MarkSpam(ctx, req.(*MarkSpamRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_UnmarkSpam_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).UnmarkSpam(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_UnmarkSpam_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).UnmarkSpam(ctx, req.(*EventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListSpamEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListSpamEvents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListSpamEvents_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListSpamEvents(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_RateLimitCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RateLimitCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).RateLimitCheck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_RateLimitCheck_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).RateLimitCheck(ctx, req.(*RateLimitCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ProcessConfigEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConfigEventRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ProcessConfigEvent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ProcessConfigEvent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ProcessConfigEvent(ctx, req.(*ConfigEventRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetCuratingConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetCuratingConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetCuratingConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetCuratingConfig(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_IsCuratingConfigured_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).IsCuratingConfigured(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_IsCuratingConfigured_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).IsCuratingConfigured(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ListUnclassifiedUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PaginationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ListUnclassifiedUsers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ListUnclassifiedUsers_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ListUnclassifiedUsers(ctx, req.(*PaginationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_GetEventsForPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetEventsForPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).GetEventsForPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_GetEventsForPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).GetEventsForPubkey(ctx, req.(*GetEventsForPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_DeleteEventsForPubkey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteEventsForPubkeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).DeleteEventsForPubkey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_DeleteEventsForPubkey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).DeleteEventsForPubkey(ctx, req.(*DeleteEventsForPubkeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ACLService_ScanAllPubkeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ACLServiceServer).ScanAllPubkeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ACLService_ScanAllPubkeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ACLServiceServer).ScanAllPubkeys(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +// ACLService_ServiceDesc is the grpc.ServiceDesc for ACLService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ACLService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "orlyacl.v1.ACLService", + HandlerType: (*ACLServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetAccessLevel", + Handler: _ACLService_GetAccessLevel_Handler, + }, + { + MethodName: "CheckPolicy", + Handler: _ACLService_CheckPolicy_Handler, + }, + { + MethodName: "GetACLInfo", + Handler: _ACLService_GetACLInfo_Handler, + }, + { + MethodName: "GetMode", + Handler: _ACLService_GetMode_Handler, + }, + { + MethodName: "Ready", + Handler: _ACLService_Ready_Handler, + }, + { + MethodName: "GetThrottleDelay", + Handler: _ACLService_GetThrottleDelay_Handler, + }, + { + MethodName: "AddFollow", + Handler: _ACLService_AddFollow_Handler, + }, + { + MethodName: "GetFollowedPubkeys", + Handler: _ACLService_GetFollowedPubkeys_Handler, + }, + { + MethodName: "GetAdminRelays", + Handler: _ACLService_GetAdminRelays_Handler, + }, + { + MethodName: "BanPubkey", + Handler: _ACLService_BanPubkey_Handler, + }, + { + MethodName: "UnbanPubkey", + Handler: _ACLService_UnbanPubkey_Handler, + }, + { + MethodName: "ListBannedPubkeys", + Handler: _ACLService_ListBannedPubkeys_Handler, + }, + { + MethodName: "AllowPubkey", + Handler: _ACLService_AllowPubkey_Handler, + }, + { + MethodName: "DisallowPubkey", + Handler: _ACLService_DisallowPubkey_Handler, + }, + { + MethodName: "ListAllowedPubkeys", + Handler: _ACLService_ListAllowedPubkeys_Handler, + }, + { + MethodName: "BanEvent", + Handler: _ACLService_BanEvent_Handler, + }, + { + MethodName: "UnbanEvent", + Handler: _ACLService_UnbanEvent_Handler, + }, + { + MethodName: "ListBannedEvents", + Handler: _ACLService_ListBannedEvents_Handler, + }, + { + MethodName: "AllowEvent", + Handler: _ACLService_AllowEvent_Handler, + }, + { + MethodName: "DisallowEvent", + Handler: _ACLService_DisallowEvent_Handler, + }, + { + MethodName: "ListAllowedEvents", + Handler: _ACLService_ListAllowedEvents_Handler, + }, + { + MethodName: "BlockIP", + Handler: _ACLService_BlockIP_Handler, + }, + { + MethodName: "UnblockIP", + Handler: _ACLService_UnblockIP_Handler, + }, + { + MethodName: "ListBlockedIPs", + Handler: _ACLService_ListBlockedIPs_Handler, + }, + { + MethodName: "AllowKind", + Handler: _ACLService_AllowKind_Handler, + }, + { + MethodName: "DisallowKind", + Handler: _ACLService_DisallowKind_Handler, + }, + { + MethodName: "ListAllowedKinds", + Handler: _ACLService_ListAllowedKinds_Handler, + }, + { + MethodName: "UpdatePeerAdmins", + Handler: _ACLService_UpdatePeerAdmins_Handler, + }, + { + MethodName: "TrustPubkey", + Handler: _ACLService_TrustPubkey_Handler, + }, + { + MethodName: "UntrustPubkey", + Handler: _ACLService_UntrustPubkey_Handler, + }, + { + MethodName: "ListTrustedPubkeys", + Handler: _ACLService_ListTrustedPubkeys_Handler, + }, + { + MethodName: "BlacklistPubkey", + Handler: _ACLService_BlacklistPubkey_Handler, + }, + { + MethodName: "UnblacklistPubkey", + Handler: _ACLService_UnblacklistPubkey_Handler, + }, + { + MethodName: "ListBlacklistedPubkeys", + Handler: _ACLService_ListBlacklistedPubkeys_Handler, + }, + { + MethodName: "MarkSpam", + Handler: _ACLService_MarkSpam_Handler, + }, + { + MethodName: "UnmarkSpam", + Handler: _ACLService_UnmarkSpam_Handler, + }, + { + MethodName: "ListSpamEvents", + Handler: _ACLService_ListSpamEvents_Handler, + }, + { + MethodName: "RateLimitCheck", + Handler: _ACLService_RateLimitCheck_Handler, + }, + { + MethodName: "ProcessConfigEvent", + Handler: _ACLService_ProcessConfigEvent_Handler, + }, + { + MethodName: "GetCuratingConfig", + Handler: _ACLService_GetCuratingConfig_Handler, + }, + { + MethodName: "IsCuratingConfigured", + Handler: _ACLService_IsCuratingConfigured_Handler, + }, + { + MethodName: "ListUnclassifiedUsers", + Handler: _ACLService_ListUnclassifiedUsers_Handler, + }, + { + MethodName: "GetEventsForPubkey", + Handler: _ACLService_GetEventsForPubkey_Handler, + }, + { + MethodName: "DeleteEventsForPubkey", + Handler: _ACLService_DeleteEventsForPubkey_Handler, + }, + { + MethodName: "ScanAllPubkeys", + Handler: _ACLService_ScanAllPubkeys_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "orlyacl/v1/acl.proto", +} diff --git a/pkg/proto/orlyacl/v1/types.pb.go b/pkg/proto/orlyacl/v1/types.pb.go new file mode 100644 index 0000000..5509ba0 --- /dev/null +++ b/pkg/proto/orlyacl/v1/types.pb.go @@ -0,0 +1,3234 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: orlyacl/v1/types.proto + +package orlyaclv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + v1 "next.orly.dev/pkg/proto/orlydb/v1" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +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) +) + +// Empty is used for requests/responses with no data +type Empty struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Empty) Reset() { + *x = Empty{} + mi := &file_orlyacl_v1_types_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{0} +} + +type AccessLevelRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AccessLevelRequest) Reset() { + *x = AccessLevelRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AccessLevelRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccessLevelRequest) ProtoMessage() {} + +func (x *AccessLevelRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AccessLevelRequest.ProtoReflect.Descriptor instead. +func (*AccessLevelRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{1} +} + +func (x *AccessLevelRequest) GetPubkey() []byte { + if x != nil { + return x.Pubkey + } + return nil +} + +func (x *AccessLevelRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type AccessLevelResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Level string `protobuf:"bytes,1,opt,name=level,proto3" json:"level,omitempty"` // none/read/write/admin/owner/banned/blocked + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AccessLevelResponse) Reset() { + *x = AccessLevelResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AccessLevelResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccessLevelResponse) ProtoMessage() {} + +func (x *AccessLevelResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AccessLevelResponse.ProtoReflect.Descriptor instead. +func (*AccessLevelResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{2} +} + +func (x *AccessLevelResponse) GetLevel() string { + if x != nil { + return x.Level + } + return "" +} + +type ACLInfoResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Documentation string `protobuf:"bytes,3,opt,name=documentation,proto3" json:"documentation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ACLInfoResponse) Reset() { + *x = ACLInfoResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ACLInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ACLInfoResponse) ProtoMessage() {} + +func (x *ACLInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ACLInfoResponse.ProtoReflect.Descriptor instead. +func (*ACLInfoResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{3} +} + +func (x *ACLInfoResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ACLInfoResponse) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ACLInfoResponse) GetDocumentation() string { + if x != nil { + return x.Documentation + } + return "" +} + +type ModeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Mode string `protobuf:"bytes,1,opt,name=mode,proto3" json:"mode,omitempty"` // none/follows/managed/curating + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ModeResponse) Reset() { + *x = ModeResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ModeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ModeResponse) ProtoMessage() {} + +func (x *ModeResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ModeResponse.ProtoReflect.Descriptor instead. +func (*ModeResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{4} +} + +func (x *ModeResponse) GetMode() string { + if x != nil { + return x.Mode + } + return "" +} + +type ReadyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ready bool `protobuf:"varint,1,opt,name=ready,proto3" json:"ready,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReadyResponse) Reset() { + *x = ReadyResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReadyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadyResponse) ProtoMessage() {} + +func (x *ReadyResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReadyResponse.ProtoReflect.Descriptor instead. +func (*ReadyResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{5} +} + +func (x *ReadyResponse) GetReady() bool { + if x != nil { + return x.Ready + } + return false +} + +type BoolResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BoolResponse) Reset() { + *x = BoolResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BoolResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BoolResponse) ProtoMessage() {} + +func (x *BoolResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BoolResponse.ProtoReflect.Descriptor instead. +func (*BoolResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{6} +} + +func (x *BoolResponse) GetValue() bool { + if x != nil { + return x.Value + } + return false +} + +type PolicyCheckRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Event *v1.Event `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PolicyCheckRequest) Reset() { + *x = PolicyCheckRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PolicyCheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyCheckRequest) ProtoMessage() {} + +func (x *PolicyCheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyCheckRequest.ProtoReflect.Descriptor instead. +func (*PolicyCheckRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{7} +} + +func (x *PolicyCheckRequest) GetEvent() *v1.Event { + if x != nil { + return x.Event + } + return nil +} + +type PolicyCheckResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PolicyCheckResponse) Reset() { + *x = PolicyCheckResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PolicyCheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyCheckResponse) ProtoMessage() {} + +func (x *PolicyCheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyCheckResponse.ProtoReflect.Descriptor instead. +func (*PolicyCheckResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{8} +} + +func (x *PolicyCheckResponse) GetAllowed() bool { + if x != nil { + return x.Allowed + } + return false +} + +func (x *PolicyCheckResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type ThrottleDelayRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ThrottleDelayRequest) Reset() { + *x = ThrottleDelayRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ThrottleDelayRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThrottleDelayRequest) ProtoMessage() {} + +func (x *ThrottleDelayRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ThrottleDelayRequest.ProtoReflect.Descriptor instead. +func (*ThrottleDelayRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{9} +} + +func (x *ThrottleDelayRequest) GetPubkey() []byte { + if x != nil { + return x.Pubkey + } + return nil +} + +func (x *ThrottleDelayRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +type ThrottleDelayResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + DelayMs int64 `protobuf:"varint,1,opt,name=delay_ms,json=delayMs,proto3" json:"delay_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ThrottleDelayResponse) Reset() { + *x = ThrottleDelayResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ThrottleDelayResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThrottleDelayResponse) ProtoMessage() {} + +func (x *ThrottleDelayResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ThrottleDelayResponse.ProtoReflect.Descriptor instead. +func (*ThrottleDelayResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{10} +} + +func (x *ThrottleDelayResponse) GetDelayMs() int64 { + if x != nil { + return x.DelayMs + } + return 0 +} + +type AddFollowRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddFollowRequest) Reset() { + *x = AddFollowRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddFollowRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFollowRequest) ProtoMessage() {} + +func (x *AddFollowRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFollowRequest.ProtoReflect.Descriptor instead. +func (*AddFollowRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{11} +} + +func (x *AddFollowRequest) GetPubkey() []byte { + if x != nil { + return x.Pubkey + } + return nil +} + +type FollowedPubkeysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkeys [][]byte `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FollowedPubkeysResponse) Reset() { + *x = FollowedPubkeysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FollowedPubkeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FollowedPubkeysResponse) ProtoMessage() {} + +func (x *FollowedPubkeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FollowedPubkeysResponse.ProtoReflect.Descriptor instead. +func (*FollowedPubkeysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{12} +} + +func (x *FollowedPubkeysResponse) GetPubkeys() [][]byte { + if x != nil { + return x.Pubkeys + } + return nil +} + +type AdminRelaysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Urls []string `protobuf:"bytes,1,rep,name=urls,proto3" json:"urls,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdminRelaysResponse) Reset() { + *x = AdminRelaysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminRelaysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminRelaysResponse) ProtoMessage() {} + +func (x *AdminRelaysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdminRelaysResponse.ProtoReflect.Descriptor instead. +func (*AdminRelaysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{13} +} + +func (x *AdminRelaysResponse) GetUrls() []string { + if x != nil { + return x.Urls + } + return nil +} + +type PubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PubkeyRequest) Reset() { + *x = PubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PubkeyRequest) ProtoMessage() {} + +func (x *PubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PubkeyRequest.ProtoReflect.Descriptor instead. +func (*PubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{14} +} + +func (x *PubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +type IPRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IPRequest) Reset() { + *x = IPRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IPRequest) ProtoMessage() {} + +func (x *IPRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IPRequest.ProtoReflect.Descriptor instead. +func (*IPRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{15} +} + +func (x *IPRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +type BanPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BanPubkeyRequest) Reset() { + *x = BanPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BanPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BanPubkeyRequest) ProtoMessage() {} + +func (x *BanPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BanPubkeyRequest.ProtoReflect.Descriptor instead. +func (*BanPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{16} +} + +func (x *BanPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *BanPubkeyRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type AllowPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AllowPubkeyRequest) Reset() { + *x = AllowPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AllowPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllowPubkeyRequest) ProtoMessage() {} + +func (x *AllowPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllowPubkeyRequest.ProtoReflect.Descriptor instead. +func (*AllowPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{17} +} + +func (x *AllowPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *AllowPubkeyRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type BannedPubkey struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BannedPubkey) Reset() { + *x = BannedPubkey{} + mi := &file_orlyacl_v1_types_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BannedPubkey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BannedPubkey) ProtoMessage() {} + +func (x *BannedPubkey) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BannedPubkey.ProtoReflect.Descriptor instead. +func (*BannedPubkey) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{18} +} + +func (x *BannedPubkey) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *BannedPubkey) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *BannedPubkey) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type AllowedPubkey struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AllowedPubkey) Reset() { + *x = AllowedPubkey{} + mi := &file_orlyacl_v1_types_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AllowedPubkey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllowedPubkey) ProtoMessage() {} + +func (x *AllowedPubkey) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllowedPubkey.ProtoReflect.Descriptor instead. +func (*AllowedPubkey) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{19} +} + +func (x *AllowedPubkey) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *AllowedPubkey) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *AllowedPubkey) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type BanEventRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BanEventRequest) Reset() { + *x = BanEventRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BanEventRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BanEventRequest) ProtoMessage() {} + +func (x *BanEventRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BanEventRequest.ProtoReflect.Descriptor instead. +func (*BanEventRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{20} +} + +func (x *BanEventRequest) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *BanEventRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type EventRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EventRequest) Reset() { + *x = EventRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EventRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventRequest) ProtoMessage() {} + +func (x *EventRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EventRequest.ProtoReflect.Descriptor instead. +func (*EventRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{21} +} + +func (x *EventRequest) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +type BannedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BannedEvent) Reset() { + *x = BannedEvent{} + mi := &file_orlyacl_v1_types_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BannedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BannedEvent) ProtoMessage() {} + +func (x *BannedEvent) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BannedEvent.ProtoReflect.Descriptor instead. +func (*BannedEvent) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{22} +} + +func (x *BannedEvent) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *BannedEvent) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *BannedEvent) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type AllowedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AllowedEvent) Reset() { + *x = AllowedEvent{} + mi := &file_orlyacl_v1_types_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AllowedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllowedEvent) ProtoMessage() {} + +func (x *AllowedEvent) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllowedEvent.ProtoReflect.Descriptor instead. +func (*AllowedEvent) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{23} +} + +func (x *AllowedEvent) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *AllowedEvent) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *AllowedEvent) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type BlockIPRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlockIPRequest) Reset() { + *x = BlockIPRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlockIPRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockIPRequest) ProtoMessage() {} + +func (x *BlockIPRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlockIPRequest.ProtoReflect.Descriptor instead. +func (*BlockIPRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{24} +} + +func (x *BlockIPRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *BlockIPRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type BlockedIP struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlockedIP) Reset() { + *x = BlockedIP{} + mi := &file_orlyacl_v1_types_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlockedIP) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockedIP) ProtoMessage() {} + +func (x *BlockedIP) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlockedIP.ProtoReflect.Descriptor instead. +func (*BlockedIP) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{25} +} + +func (x *BlockedIP) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *BlockedIP) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *BlockedIP) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type AllowKindRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Kind int32 `protobuf:"varint,1,opt,name=kind,proto3" json:"kind,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AllowKindRequest) Reset() { + *x = AllowKindRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AllowKindRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllowKindRequest) ProtoMessage() {} + +func (x *AllowKindRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllowKindRequest.ProtoReflect.Descriptor instead. +func (*AllowKindRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{26} +} + +func (x *AllowKindRequest) GetKind() int32 { + if x != nil { + return x.Kind + } + return 0 +} + +type KindRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Kind int32 `protobuf:"varint,1,opt,name=kind,proto3" json:"kind,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *KindRequest) Reset() { + *x = KindRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *KindRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KindRequest) ProtoMessage() {} + +func (x *KindRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KindRequest.ProtoReflect.Descriptor instead. +func (*KindRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{27} +} + +func (x *KindRequest) GetKind() int32 { + if x != nil { + return x.Kind + } + return 0 +} + +type UpdatePeerAdminsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PeerPubkeys [][]byte `protobuf:"bytes,1,rep,name=peer_pubkeys,json=peerPubkeys,proto3" json:"peer_pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdatePeerAdminsRequest) Reset() { + *x = UpdatePeerAdminsRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdatePeerAdminsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePeerAdminsRequest) ProtoMessage() {} + +func (x *UpdatePeerAdminsRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdatePeerAdminsRequest.ProtoReflect.Descriptor instead. +func (*UpdatePeerAdminsRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{28} +} + +func (x *UpdatePeerAdminsRequest) GetPeerPubkeys() [][]byte { + if x != nil { + return x.PeerPubkeys + } + return nil +} + +type ListBannedPubkeysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkeys []*BannedPubkey `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBannedPubkeysResponse) Reset() { + *x = ListBannedPubkeysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBannedPubkeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBannedPubkeysResponse) ProtoMessage() {} + +func (x *ListBannedPubkeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListBannedPubkeysResponse.ProtoReflect.Descriptor instead. +func (*ListBannedPubkeysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{29} +} + +func (x *ListBannedPubkeysResponse) GetPubkeys() []*BannedPubkey { + if x != nil { + return x.Pubkeys + } + return nil +} + +type ListAllowedPubkeysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkeys []*AllowedPubkey `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListAllowedPubkeysResponse) Reset() { + *x = ListAllowedPubkeysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListAllowedPubkeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAllowedPubkeysResponse) ProtoMessage() {} + +func (x *ListAllowedPubkeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAllowedPubkeysResponse.ProtoReflect.Descriptor instead. +func (*ListAllowedPubkeysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{30} +} + +func (x *ListAllowedPubkeysResponse) GetPubkeys() []*AllowedPubkey { + if x != nil { + return x.Pubkeys + } + return nil +} + +type ListBannedEventsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*BannedEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBannedEventsResponse) Reset() { + *x = ListBannedEventsResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBannedEventsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBannedEventsResponse) ProtoMessage() {} + +func (x *ListBannedEventsResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListBannedEventsResponse.ProtoReflect.Descriptor instead. +func (*ListBannedEventsResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{31} +} + +func (x *ListBannedEventsResponse) GetEvents() []*BannedEvent { + if x != nil { + return x.Events + } + return nil +} + +type ListAllowedEventsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*AllowedEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListAllowedEventsResponse) Reset() { + *x = ListAllowedEventsResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListAllowedEventsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAllowedEventsResponse) ProtoMessage() {} + +func (x *ListAllowedEventsResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAllowedEventsResponse.ProtoReflect.Descriptor instead. +func (*ListAllowedEventsResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{32} +} + +func (x *ListAllowedEventsResponse) GetEvents() []*AllowedEvent { + if x != nil { + return x.Events + } + return nil +} + +type ListBlockedIPsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ips []*BlockedIP `protobuf:"bytes,1,rep,name=ips,proto3" json:"ips,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBlockedIPsResponse) Reset() { + *x = ListBlockedIPsResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBlockedIPsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBlockedIPsResponse) ProtoMessage() {} + +func (x *ListBlockedIPsResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListBlockedIPsResponse.ProtoReflect.Descriptor instead. +func (*ListBlockedIPsResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{33} +} + +func (x *ListBlockedIPsResponse) GetIps() []*BlockedIP { + if x != nil { + return x.Ips + } + return nil +} + +type ListAllowedKindsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Kinds []int32 `protobuf:"varint,1,rep,packed,name=kinds,proto3" json:"kinds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListAllowedKindsResponse) Reset() { + *x = ListAllowedKindsResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListAllowedKindsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAllowedKindsResponse) ProtoMessage() {} + +func (x *ListAllowedKindsResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[34] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAllowedKindsResponse.ProtoReflect.Descriptor instead. +func (*ListAllowedKindsResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{34} +} + +func (x *ListAllowedKindsResponse) GetKinds() []int32 { + if x != nil { + return x.Kinds + } + return nil +} + +type TrustPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Note string `protobuf:"bytes,2,opt,name=note,proto3" json:"note,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TrustPubkeyRequest) Reset() { + *x = TrustPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TrustPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrustPubkeyRequest) ProtoMessage() {} + +func (x *TrustPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TrustPubkeyRequest.ProtoReflect.Descriptor instead. +func (*TrustPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{35} +} + +func (x *TrustPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *TrustPubkeyRequest) GetNote() string { + if x != nil { + return x.Note + } + return "" +} + +type BlacklistPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlacklistPubkeyRequest) Reset() { + *x = BlacklistPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlacklistPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlacklistPubkeyRequest) ProtoMessage() {} + +func (x *BlacklistPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[36] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlacklistPubkeyRequest.ProtoReflect.Descriptor instead. +func (*BlacklistPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{36} +} + +func (x *BlacklistPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *BlacklistPubkeyRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type TrustedPubkey struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Note string `protobuf:"bytes,2,opt,name=note,proto3" json:"note,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TrustedPubkey) Reset() { + *x = TrustedPubkey{} + mi := &file_orlyacl_v1_types_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TrustedPubkey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrustedPubkey) ProtoMessage() {} + +func (x *TrustedPubkey) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[37] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TrustedPubkey.ProtoReflect.Descriptor instead. +func (*TrustedPubkey) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{37} +} + +func (x *TrustedPubkey) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *TrustedPubkey) GetNote() string { + if x != nil { + return x.Note + } + return "" +} + +func (x *TrustedPubkey) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type BlacklistedPubkey struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,3,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BlacklistedPubkey) Reset() { + *x = BlacklistedPubkey{} + mi := &file_orlyacl_v1_types_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BlacklistedPubkey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlacklistedPubkey) ProtoMessage() {} + +func (x *BlacklistedPubkey) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlacklistedPubkey.ProtoReflect.Descriptor instead. +func (*BlacklistedPubkey) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{38} +} + +func (x *BlacklistedPubkey) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *BlacklistedPubkey) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *BlacklistedPubkey) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type MarkSpamRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + Pubkey string `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MarkSpamRequest) Reset() { + *x = MarkSpamRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MarkSpamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MarkSpamRequest) ProtoMessage() {} + +func (x *MarkSpamRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MarkSpamRequest.ProtoReflect.Descriptor instead. +func (*MarkSpamRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{39} +} + +func (x *MarkSpamRequest) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *MarkSpamRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *MarkSpamRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type SpamEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + Pubkey string `protobuf:"bytes,2,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + Added int64 `protobuf:"varint,4,opt,name=added,proto3" json:"added,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SpamEvent) Reset() { + *x = SpamEvent{} + mi := &file_orlyacl_v1_types_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SpamEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpamEvent) ProtoMessage() {} + +func (x *SpamEvent) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SpamEvent.ProtoReflect.Descriptor instead. +func (*SpamEvent) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{40} +} + +func (x *SpamEvent) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *SpamEvent) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *SpamEvent) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *SpamEvent) GetAdded() int64 { + if x != nil { + return x.Added + } + return 0 +} + +type RateLimitCheckRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RateLimitCheckRequest) Reset() { + *x = RateLimitCheckRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RateLimitCheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RateLimitCheckRequest) ProtoMessage() {} + +func (x *RateLimitCheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[41] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RateLimitCheckRequest.ProtoReflect.Descriptor instead. +func (*RateLimitCheckRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{41} +} + +func (x *RateLimitCheckRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *RateLimitCheckRequest) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +type RateLimitCheckResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RateLimitCheckResponse) Reset() { + *x = RateLimitCheckResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RateLimitCheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RateLimitCheckResponse) ProtoMessage() {} + +func (x *RateLimitCheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[42] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RateLimitCheckResponse.ProtoReflect.Descriptor instead. +func (*RateLimitCheckResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{42} +} + +func (x *RateLimitCheckResponse) GetAllowed() bool { + if x != nil { + return x.Allowed + } + return false +} + +func (x *RateLimitCheckResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type ConfigEventRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Event *v1.Event `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigEventRequest) Reset() { + *x = ConfigEventRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigEventRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigEventRequest) ProtoMessage() {} + +func (x *ConfigEventRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[43] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigEventRequest.ProtoReflect.Descriptor instead. +func (*ConfigEventRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{43} +} + +func (x *ConfigEventRequest) GetEvent() *v1.Event { + if x != nil { + return x.Event + } + return nil +} + +type CuratingConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + ConfigEventId string `protobuf:"bytes,1,opt,name=config_event_id,json=configEventId,proto3" json:"config_event_id,omitempty"` + ConfigPubkey string `protobuf:"bytes,2,opt,name=config_pubkey,json=configPubkey,proto3" json:"config_pubkey,omitempty"` + ConfiguredAt int64 `protobuf:"varint,3,opt,name=configured_at,json=configuredAt,proto3" json:"configured_at,omitempty"` + DailyLimit int32 `protobuf:"varint,4,opt,name=daily_limit,json=dailyLimit,proto3" json:"daily_limit,omitempty"` + IpDailyLimit int32 `protobuf:"varint,5,opt,name=ip_daily_limit,json=ipDailyLimit,proto3" json:"ip_daily_limit,omitempty"` + FirstBanHours int32 `protobuf:"varint,6,opt,name=first_ban_hours,json=firstBanHours,proto3" json:"first_ban_hours,omitempty"` + SecondBanHours int32 `protobuf:"varint,7,opt,name=second_ban_hours,json=secondBanHours,proto3" json:"second_ban_hours,omitempty"` + KindCategories []string `protobuf:"bytes,8,rep,name=kind_categories,json=kindCategories,proto3" json:"kind_categories,omitempty"` + AllowedRanges []string `protobuf:"bytes,9,rep,name=allowed_ranges,json=allowedRanges,proto3" json:"allowed_ranges,omitempty"` + AllowedKinds []int32 `protobuf:"varint,10,rep,packed,name=allowed_kinds,json=allowedKinds,proto3" json:"allowed_kinds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CuratingConfig) Reset() { + *x = CuratingConfig{} + mi := &file_orlyacl_v1_types_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CuratingConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CuratingConfig) ProtoMessage() {} + +func (x *CuratingConfig) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[44] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CuratingConfig.ProtoReflect.Descriptor instead. +func (*CuratingConfig) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{44} +} + +func (x *CuratingConfig) GetConfigEventId() string { + if x != nil { + return x.ConfigEventId + } + return "" +} + +func (x *CuratingConfig) GetConfigPubkey() string { + if x != nil { + return x.ConfigPubkey + } + return "" +} + +func (x *CuratingConfig) GetConfiguredAt() int64 { + if x != nil { + return x.ConfiguredAt + } + return 0 +} + +func (x *CuratingConfig) GetDailyLimit() int32 { + if x != nil { + return x.DailyLimit + } + return 0 +} + +func (x *CuratingConfig) GetIpDailyLimit() int32 { + if x != nil { + return x.IpDailyLimit + } + return 0 +} + +func (x *CuratingConfig) GetFirstBanHours() int32 { + if x != nil { + return x.FirstBanHours + } + return 0 +} + +func (x *CuratingConfig) GetSecondBanHours() int32 { + if x != nil { + return x.SecondBanHours + } + return 0 +} + +func (x *CuratingConfig) GetKindCategories() []string { + if x != nil { + return x.KindCategories + } + return nil +} + +func (x *CuratingConfig) GetAllowedRanges() []string { + if x != nil { + return x.AllowedRanges + } + return nil +} + +func (x *CuratingConfig) GetAllowedKinds() []int32 { + if x != nil { + return x.AllowedKinds + } + return nil +} + +type UnclassifiedUser struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + EventCount int32 `protobuf:"varint,2,opt,name=event_count,json=eventCount,proto3" json:"event_count,omitempty"` + FirstSeen string `protobuf:"bytes,3,opt,name=first_seen,json=firstSeen,proto3" json:"first_seen,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnclassifiedUser) Reset() { + *x = UnclassifiedUser{} + mi := &file_orlyacl_v1_types_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnclassifiedUser) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnclassifiedUser) ProtoMessage() {} + +func (x *UnclassifiedUser) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[45] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnclassifiedUser.ProtoReflect.Descriptor instead. +func (*UnclassifiedUser) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{45} +} + +func (x *UnclassifiedUser) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *UnclassifiedUser) GetEventCount() int32 { + if x != nil { + return x.EventCount + } + return 0 +} + +func (x *UnclassifiedUser) GetFirstSeen() string { + if x != nil { + return x.FirstSeen + } + return "" +} + +type PaginationRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` + Offset int32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PaginationRequest) Reset() { + *x = PaginationRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PaginationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaginationRequest) ProtoMessage() {} + +func (x *PaginationRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[46] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaginationRequest.ProtoReflect.Descriptor instead. +func (*PaginationRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{46} +} + +func (x *PaginationRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *PaginationRequest) GetOffset() int32 { + if x != nil { + return x.Offset + } + return 0 +} + +type ListTrustedPubkeysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkeys []*TrustedPubkey `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListTrustedPubkeysResponse) Reset() { + *x = ListTrustedPubkeysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListTrustedPubkeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTrustedPubkeysResponse) ProtoMessage() {} + +func (x *ListTrustedPubkeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[47] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTrustedPubkeysResponse.ProtoReflect.Descriptor instead. +func (*ListTrustedPubkeysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{47} +} + +func (x *ListTrustedPubkeysResponse) GetPubkeys() []*TrustedPubkey { + if x != nil { + return x.Pubkeys + } + return nil +} + +type ListBlacklistedPubkeysResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkeys []*BlacklistedPubkey `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBlacklistedPubkeysResponse) Reset() { + *x = ListBlacklistedPubkeysResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBlacklistedPubkeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBlacklistedPubkeysResponse) ProtoMessage() {} + +func (x *ListBlacklistedPubkeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[48] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListBlacklistedPubkeysResponse.ProtoReflect.Descriptor instead. +func (*ListBlacklistedPubkeysResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{48} +} + +func (x *ListBlacklistedPubkeysResponse) GetPubkeys() []*BlacklistedPubkey { + if x != nil { + return x.Pubkeys + } + return nil +} + +type ListSpamEventsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*SpamEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSpamEventsResponse) Reset() { + *x = ListSpamEventsResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSpamEventsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSpamEventsResponse) ProtoMessage() {} + +func (x *ListSpamEventsResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[49] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListSpamEventsResponse.ProtoReflect.Descriptor instead. +func (*ListSpamEventsResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{49} +} + +func (x *ListSpamEventsResponse) GetEvents() []*SpamEvent { + if x != nil { + return x.Events + } + return nil +} + +type ListUnclassifiedUsersResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Users []*UnclassifiedUser `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListUnclassifiedUsersResponse) Reset() { + *x = ListUnclassifiedUsersResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListUnclassifiedUsersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListUnclassifiedUsersResponse) ProtoMessage() {} + +func (x *ListUnclassifiedUsersResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[50] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListUnclassifiedUsersResponse.ProtoReflect.Descriptor instead. +func (*ListUnclassifiedUsersResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{50} +} + +func (x *ListUnclassifiedUsersResponse) GetUsers() []*UnclassifiedUser { + if x != nil { + return x.Users + } + return nil +} + +func (x *ListUnclassifiedUsersResponse) GetTotal() int32 { + if x != nil { + return x.Total + } + return 0 +} + +type GetEventsForPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` + Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEventsForPubkeyRequest) Reset() { + *x = GetEventsForPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEventsForPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventsForPubkeyRequest) ProtoMessage() {} + +func (x *GetEventsForPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[51] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEventsForPubkeyRequest.ProtoReflect.Descriptor instead. +func (*GetEventsForPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{51} +} + +func (x *GetEventsForPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +func (x *GetEventsForPubkeyRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *GetEventsForPubkeyRequest) GetOffset() int32 { + if x != nil { + return x.Offset + } + return 0 +} + +type EventSummary struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Kind uint32 `protobuf:"varint,2,opt,name=kind,proto3" json:"kind,omitempty"` + Content []byte `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` + CreatedAt int64 `protobuf:"varint,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EventSummary) Reset() { + *x = EventSummary{} + mi := &file_orlyacl_v1_types_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EventSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventSummary) ProtoMessage() {} + +func (x *EventSummary) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[52] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EventSummary.ProtoReflect.Descriptor instead. +func (*EventSummary) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{52} +} + +func (x *EventSummary) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *EventSummary) GetKind() uint32 { + if x != nil { + return x.Kind + } + return 0 +} + +func (x *EventSummary) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +func (x *EventSummary) GetCreatedAt() int64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +type EventsForPubkeyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*EventSummary `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + Total int32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EventsForPubkeyResponse) Reset() { + *x = EventsForPubkeyResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EventsForPubkeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventsForPubkeyResponse) ProtoMessage() {} + +func (x *EventsForPubkeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[53] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EventsForPubkeyResponse.ProtoReflect.Descriptor instead. +func (*EventsForPubkeyResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{53} +} + +func (x *EventsForPubkeyResponse) GetEvents() []*EventSummary { + if x != nil { + return x.Events + } + return nil +} + +func (x *EventsForPubkeyResponse) GetTotal() int32 { + if x != nil { + return x.Total + } + return 0 +} + +type DeleteEventsForPubkeyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteEventsForPubkeyRequest) Reset() { + *x = DeleteEventsForPubkeyRequest{} + mi := &file_orlyacl_v1_types_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteEventsForPubkeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteEventsForPubkeyRequest) ProtoMessage() {} + +func (x *DeleteEventsForPubkeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[54] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteEventsForPubkeyRequest.ProtoReflect.Descriptor instead. +func (*DeleteEventsForPubkeyRequest) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{54} +} + +func (x *DeleteEventsForPubkeyRequest) GetPubkey() string { + if x != nil { + return x.Pubkey + } + return "" +} + +type DeleteCountResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteCountResponse) Reset() { + *x = DeleteCountResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteCountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteCountResponse) ProtoMessage() {} + +func (x *DeleteCountResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[55] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteCountResponse.ProtoReflect.Descriptor instead. +func (*DeleteCountResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{55} +} + +func (x *DeleteCountResponse) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + +type ScanResultResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TotalPubkeys int32 `protobuf:"varint,1,opt,name=total_pubkeys,json=totalPubkeys,proto3" json:"total_pubkeys,omitempty"` + TotalEvents int32 `protobuf:"varint,2,opt,name=total_events,json=totalEvents,proto3" json:"total_events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ScanResultResponse) Reset() { + *x = ScanResultResponse{} + mi := &file_orlyacl_v1_types_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ScanResultResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScanResultResponse) ProtoMessage() {} + +func (x *ScanResultResponse) ProtoReflect() protoreflect.Message { + mi := &file_orlyacl_v1_types_proto_msgTypes[56] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScanResultResponse.ProtoReflect.Descriptor instead. +func (*ScanResultResponse) Descriptor() ([]byte, []int) { + return file_orlyacl_v1_types_proto_rawDescGZIP(), []int{56} +} + +func (x *ScanResultResponse) GetTotalPubkeys() int32 { + if x != nil { + return x.TotalPubkeys + } + return 0 +} + +func (x *ScanResultResponse) GetTotalEvents() int32 { + if x != nil { + return x.TotalEvents + } + return 0 +} + +var File_orlyacl_v1_types_proto protoreflect.FileDescriptor + +const file_orlyacl_v1_types_proto_rawDesc = "" + + "\n" + + "\x16orlyacl/v1/types.proto\x12\n" + + "orlyacl.v1\x1a\x15orlydb/v1/types.proto\"\a\n" + + "\x05Empty\"F\n" + + "\x12AccessLevelRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\fR\x06pubkey\x12\x18\n" + + "\aaddress\x18\x02 \x01(\tR\aaddress\"+\n" + + "\x13AccessLevelResponse\x12\x14\n" + + "\x05level\x18\x01 \x01(\tR\x05level\"m\n" + + "\x0fACLInfoResponse\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" + + "\vdescription\x18\x02 \x01(\tR\vdescription\x12$\n" + + "\rdocumentation\x18\x03 \x01(\tR\rdocumentation\"\"\n" + + "\fModeResponse\x12\x12\n" + + "\x04mode\x18\x01 \x01(\tR\x04mode\"%\n" + + "\rReadyResponse\x12\x14\n" + + "\x05ready\x18\x01 \x01(\bR\x05ready\"$\n" + + "\fBoolResponse\x12\x14\n" + + "\x05value\x18\x01 \x01(\bR\x05value\"<\n" + + "\x12PolicyCheckRequest\x12&\n" + + "\x05event\x18\x01 \x01(\v2\x10.orlydb.v1.EventR\x05event\"E\n" + + "\x13PolicyCheckResponse\x12\x18\n" + + "\aallowed\x18\x01 \x01(\bR\aallowed\x12\x14\n" + + "\x05error\x18\x02 \x01(\tR\x05error\">\n" + + "\x14ThrottleDelayRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\fR\x06pubkey\x12\x0e\n" + + "\x02ip\x18\x02 \x01(\tR\x02ip\"2\n" + + "\x15ThrottleDelayResponse\x12\x19\n" + + "\bdelay_ms\x18\x01 \x01(\x03R\adelayMs\"*\n" + + "\x10AddFollowRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\fR\x06pubkey\"3\n" + + "\x17FollowedPubkeysResponse\x12\x18\n" + + "\apubkeys\x18\x01 \x03(\fR\apubkeys\")\n" + + "\x13AdminRelaysResponse\x12\x12\n" + + "\x04urls\x18\x01 \x03(\tR\x04urls\"'\n" + + "\rPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\"\x1b\n" + + "\tIPRequest\x12\x0e\n" + + "\x02ip\x18\x01 \x01(\tR\x02ip\"B\n" + + "\x10BanPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"D\n" + + "\x12AllowPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"T\n" + + "\fBannedPubkey\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"U\n" + + "\rAllowedPubkey\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"D\n" + + "\x0fBanEventRequest\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\")\n" + + "\fEventRequest\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\"V\n" + + "\vBannedEvent\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"W\n" + + "\fAllowedEvent\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"8\n" + + "\x0eBlockIPRequest\x12\x0e\n" + + "\x02ip\x18\x01 \x01(\tR\x02ip\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"I\n" + + "\tBlockedIP\x12\x0e\n" + + "\x02ip\x18\x01 \x01(\tR\x02ip\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"&\n" + + "\x10AllowKindRequest\x12\x12\n" + + "\x04kind\x18\x01 \x01(\x05R\x04kind\"!\n" + + "\vKindRequest\x12\x12\n" + + "\x04kind\x18\x01 \x01(\x05R\x04kind\"<\n" + + "\x17UpdatePeerAdminsRequest\x12!\n" + + "\fpeer_pubkeys\x18\x01 \x03(\fR\vpeerPubkeys\"O\n" + + "\x19ListBannedPubkeysResponse\x122\n" + + "\apubkeys\x18\x01 \x03(\v2\x18.orlyacl.v1.BannedPubkeyR\apubkeys\"Q\n" + + "\x1aListAllowedPubkeysResponse\x123\n" + + "\apubkeys\x18\x01 \x03(\v2\x19.orlyacl.v1.AllowedPubkeyR\apubkeys\"K\n" + + "\x18ListBannedEventsResponse\x12/\n" + + "\x06events\x18\x01 \x03(\v2\x17.orlyacl.v1.BannedEventR\x06events\"M\n" + + "\x19ListAllowedEventsResponse\x120\n" + + "\x06events\x18\x01 \x03(\v2\x18.orlyacl.v1.AllowedEventR\x06events\"A\n" + + "\x16ListBlockedIPsResponse\x12'\n" + + "\x03ips\x18\x01 \x03(\v2\x15.orlyacl.v1.BlockedIPR\x03ips\"0\n" + + "\x18ListAllowedKindsResponse\x12\x14\n" + + "\x05kinds\x18\x01 \x03(\x05R\x05kinds\"@\n" + + "\x12TrustPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x12\n" + + "\x04note\x18\x02 \x01(\tR\x04note\"H\n" + + "\x16BlacklistPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\"Q\n" + + "\rTrustedPubkey\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x12\n" + + "\x04note\x18\x02 \x01(\tR\x04note\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"Y\n" + + "\x11BlacklistedPubkey\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x03 \x01(\x03R\x05added\"\\\n" + + "\x0fMarkSpamRequest\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x16\n" + + "\x06pubkey\x18\x02 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\"l\n" + + "\tSpamEvent\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x16\n" + + "\x06pubkey\x18\x02 \x01(\tR\x06pubkey\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\x12\x14\n" + + "\x05added\x18\x04 \x01(\x03R\x05added\"?\n" + + "\x15RateLimitCheckRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x0e\n" + + "\x02ip\x18\x02 \x01(\tR\x02ip\"L\n" + + "\x16RateLimitCheckResponse\x12\x18\n" + + "\aallowed\x18\x01 \x01(\bR\aallowed\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\"<\n" + + "\x12ConfigEventRequest\x12&\n" + + "\x05event\x18\x01 \x01(\v2\x10.orlydb.v1.EventR\x05event\"\x90\x03\n" + + "\x0eCuratingConfig\x12&\n" + + "\x0fconfig_event_id\x18\x01 \x01(\tR\rconfigEventId\x12#\n" + + "\rconfig_pubkey\x18\x02 \x01(\tR\fconfigPubkey\x12#\n" + + "\rconfigured_at\x18\x03 \x01(\x03R\fconfiguredAt\x12\x1f\n" + + "\vdaily_limit\x18\x04 \x01(\x05R\n" + + "dailyLimit\x12$\n" + + "\x0eip_daily_limit\x18\x05 \x01(\x05R\fipDailyLimit\x12&\n" + + "\x0ffirst_ban_hours\x18\x06 \x01(\x05R\rfirstBanHours\x12(\n" + + "\x10second_ban_hours\x18\a \x01(\x05R\x0esecondBanHours\x12'\n" + + "\x0fkind_categories\x18\b \x03(\tR\x0ekindCategories\x12%\n" + + "\x0eallowed_ranges\x18\t \x03(\tR\rallowedRanges\x12#\n" + + "\rallowed_kinds\x18\n" + + " \x03(\x05R\fallowedKinds\"j\n" + + "\x10UnclassifiedUser\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x1f\n" + + "\vevent_count\x18\x02 \x01(\x05R\n" + + "eventCount\x12\x1d\n" + + "\n" + + "first_seen\x18\x03 \x01(\tR\tfirstSeen\"A\n" + + "\x11PaginationRequest\x12\x14\n" + + "\x05limit\x18\x01 \x01(\x05R\x05limit\x12\x16\n" + + "\x06offset\x18\x02 \x01(\x05R\x06offset\"Q\n" + + "\x1aListTrustedPubkeysResponse\x123\n" + + "\apubkeys\x18\x01 \x03(\v2\x19.orlyacl.v1.TrustedPubkeyR\apubkeys\"Y\n" + + "\x1eListBlacklistedPubkeysResponse\x127\n" + + "\apubkeys\x18\x01 \x03(\v2\x1d.orlyacl.v1.BlacklistedPubkeyR\apubkeys\"G\n" + + "\x16ListSpamEventsResponse\x12-\n" + + "\x06events\x18\x01 \x03(\v2\x15.orlyacl.v1.SpamEventR\x06events\"i\n" + + "\x1dListUnclassifiedUsersResponse\x122\n" + + "\x05users\x18\x01 \x03(\v2\x1c.orlyacl.v1.UnclassifiedUserR\x05users\x12\x14\n" + + "\x05total\x18\x02 \x01(\x05R\x05total\"a\n" + + "\x19GetEventsForPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\x12\x14\n" + + "\x05limit\x18\x02 \x01(\x05R\x05limit\x12\x16\n" + + "\x06offset\x18\x03 \x01(\x05R\x06offset\"k\n" + + "\fEventSummary\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" + + "\x04kind\x18\x02 \x01(\rR\x04kind\x12\x18\n" + + "\acontent\x18\x03 \x01(\fR\acontent\x12\x1d\n" + + "\n" + + "created_at\x18\x04 \x01(\x03R\tcreatedAt\"a\n" + + "\x17EventsForPubkeyResponse\x120\n" + + "\x06events\x18\x01 \x03(\v2\x18.orlyacl.v1.EventSummaryR\x06events\x12\x14\n" + + "\x05total\x18\x02 \x01(\x05R\x05total\"6\n" + + "\x1cDeleteEventsForPubkeyRequest\x12\x16\n" + + "\x06pubkey\x18\x01 \x01(\tR\x06pubkey\"+\n" + + "\x13DeleteCountResponse\x12\x14\n" + + "\x05count\x18\x01 \x01(\x05R\x05count\"\\\n" + + "\x12ScanResultResponse\x12#\n" + + "\rtotal_pubkeys\x18\x01 \x01(\x05R\ftotalPubkeys\x12!\n" + + "\ftotal_events\x18\x02 \x01(\x05R\vtotalEventsB.Z,next.orly.dev/pkg/proto/orlyacl/v1;orlyaclv1b\x06proto3" + +var ( + file_orlyacl_v1_types_proto_rawDescOnce sync.Once + file_orlyacl_v1_types_proto_rawDescData []byte +) + +func file_orlyacl_v1_types_proto_rawDescGZIP() []byte { + file_orlyacl_v1_types_proto_rawDescOnce.Do(func() { + file_orlyacl_v1_types_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_orlyacl_v1_types_proto_rawDesc), len(file_orlyacl_v1_types_proto_rawDesc))) + }) + return file_orlyacl_v1_types_proto_rawDescData +} + +var file_orlyacl_v1_types_proto_msgTypes = make([]protoimpl.MessageInfo, 57) +var file_orlyacl_v1_types_proto_goTypes = []any{ + (*Empty)(nil), // 0: orlyacl.v1.Empty + (*AccessLevelRequest)(nil), // 1: orlyacl.v1.AccessLevelRequest + (*AccessLevelResponse)(nil), // 2: orlyacl.v1.AccessLevelResponse + (*ACLInfoResponse)(nil), // 3: orlyacl.v1.ACLInfoResponse + (*ModeResponse)(nil), // 4: orlyacl.v1.ModeResponse + (*ReadyResponse)(nil), // 5: orlyacl.v1.ReadyResponse + (*BoolResponse)(nil), // 6: orlyacl.v1.BoolResponse + (*PolicyCheckRequest)(nil), // 7: orlyacl.v1.PolicyCheckRequest + (*PolicyCheckResponse)(nil), // 8: orlyacl.v1.PolicyCheckResponse + (*ThrottleDelayRequest)(nil), // 9: orlyacl.v1.ThrottleDelayRequest + (*ThrottleDelayResponse)(nil), // 10: orlyacl.v1.ThrottleDelayResponse + (*AddFollowRequest)(nil), // 11: orlyacl.v1.AddFollowRequest + (*FollowedPubkeysResponse)(nil), // 12: orlyacl.v1.FollowedPubkeysResponse + (*AdminRelaysResponse)(nil), // 13: orlyacl.v1.AdminRelaysResponse + (*PubkeyRequest)(nil), // 14: orlyacl.v1.PubkeyRequest + (*IPRequest)(nil), // 15: orlyacl.v1.IPRequest + (*BanPubkeyRequest)(nil), // 16: orlyacl.v1.BanPubkeyRequest + (*AllowPubkeyRequest)(nil), // 17: orlyacl.v1.AllowPubkeyRequest + (*BannedPubkey)(nil), // 18: orlyacl.v1.BannedPubkey + (*AllowedPubkey)(nil), // 19: orlyacl.v1.AllowedPubkey + (*BanEventRequest)(nil), // 20: orlyacl.v1.BanEventRequest + (*EventRequest)(nil), // 21: orlyacl.v1.EventRequest + (*BannedEvent)(nil), // 22: orlyacl.v1.BannedEvent + (*AllowedEvent)(nil), // 23: orlyacl.v1.AllowedEvent + (*BlockIPRequest)(nil), // 24: orlyacl.v1.BlockIPRequest + (*BlockedIP)(nil), // 25: orlyacl.v1.BlockedIP + (*AllowKindRequest)(nil), // 26: orlyacl.v1.AllowKindRequest + (*KindRequest)(nil), // 27: orlyacl.v1.KindRequest + (*UpdatePeerAdminsRequest)(nil), // 28: orlyacl.v1.UpdatePeerAdminsRequest + (*ListBannedPubkeysResponse)(nil), // 29: orlyacl.v1.ListBannedPubkeysResponse + (*ListAllowedPubkeysResponse)(nil), // 30: orlyacl.v1.ListAllowedPubkeysResponse + (*ListBannedEventsResponse)(nil), // 31: orlyacl.v1.ListBannedEventsResponse + (*ListAllowedEventsResponse)(nil), // 32: orlyacl.v1.ListAllowedEventsResponse + (*ListBlockedIPsResponse)(nil), // 33: orlyacl.v1.ListBlockedIPsResponse + (*ListAllowedKindsResponse)(nil), // 34: orlyacl.v1.ListAllowedKindsResponse + (*TrustPubkeyRequest)(nil), // 35: orlyacl.v1.TrustPubkeyRequest + (*BlacklistPubkeyRequest)(nil), // 36: orlyacl.v1.BlacklistPubkeyRequest + (*TrustedPubkey)(nil), // 37: orlyacl.v1.TrustedPubkey + (*BlacklistedPubkey)(nil), // 38: orlyacl.v1.BlacklistedPubkey + (*MarkSpamRequest)(nil), // 39: orlyacl.v1.MarkSpamRequest + (*SpamEvent)(nil), // 40: orlyacl.v1.SpamEvent + (*RateLimitCheckRequest)(nil), // 41: orlyacl.v1.RateLimitCheckRequest + (*RateLimitCheckResponse)(nil), // 42: orlyacl.v1.RateLimitCheckResponse + (*ConfigEventRequest)(nil), // 43: orlyacl.v1.ConfigEventRequest + (*CuratingConfig)(nil), // 44: orlyacl.v1.CuratingConfig + (*UnclassifiedUser)(nil), // 45: orlyacl.v1.UnclassifiedUser + (*PaginationRequest)(nil), // 46: orlyacl.v1.PaginationRequest + (*ListTrustedPubkeysResponse)(nil), // 47: orlyacl.v1.ListTrustedPubkeysResponse + (*ListBlacklistedPubkeysResponse)(nil), // 48: orlyacl.v1.ListBlacklistedPubkeysResponse + (*ListSpamEventsResponse)(nil), // 49: orlyacl.v1.ListSpamEventsResponse + (*ListUnclassifiedUsersResponse)(nil), // 50: orlyacl.v1.ListUnclassifiedUsersResponse + (*GetEventsForPubkeyRequest)(nil), // 51: orlyacl.v1.GetEventsForPubkeyRequest + (*EventSummary)(nil), // 52: orlyacl.v1.EventSummary + (*EventsForPubkeyResponse)(nil), // 53: orlyacl.v1.EventsForPubkeyResponse + (*DeleteEventsForPubkeyRequest)(nil), // 54: orlyacl.v1.DeleteEventsForPubkeyRequest + (*DeleteCountResponse)(nil), // 55: orlyacl.v1.DeleteCountResponse + (*ScanResultResponse)(nil), // 56: orlyacl.v1.ScanResultResponse + (*v1.Event)(nil), // 57: orlydb.v1.Event +} +var file_orlyacl_v1_types_proto_depIdxs = []int32{ + 57, // 0: orlyacl.v1.PolicyCheckRequest.event:type_name -> orlydb.v1.Event + 18, // 1: orlyacl.v1.ListBannedPubkeysResponse.pubkeys:type_name -> orlyacl.v1.BannedPubkey + 19, // 2: orlyacl.v1.ListAllowedPubkeysResponse.pubkeys:type_name -> orlyacl.v1.AllowedPubkey + 22, // 3: orlyacl.v1.ListBannedEventsResponse.events:type_name -> orlyacl.v1.BannedEvent + 23, // 4: orlyacl.v1.ListAllowedEventsResponse.events:type_name -> orlyacl.v1.AllowedEvent + 25, // 5: orlyacl.v1.ListBlockedIPsResponse.ips:type_name -> orlyacl.v1.BlockedIP + 57, // 6: orlyacl.v1.ConfigEventRequest.event:type_name -> orlydb.v1.Event + 37, // 7: orlyacl.v1.ListTrustedPubkeysResponse.pubkeys:type_name -> orlyacl.v1.TrustedPubkey + 38, // 8: orlyacl.v1.ListBlacklistedPubkeysResponse.pubkeys:type_name -> orlyacl.v1.BlacklistedPubkey + 40, // 9: orlyacl.v1.ListSpamEventsResponse.events:type_name -> orlyacl.v1.SpamEvent + 45, // 10: orlyacl.v1.ListUnclassifiedUsersResponse.users:type_name -> orlyacl.v1.UnclassifiedUser + 52, // 11: orlyacl.v1.EventsForPubkeyResponse.events:type_name -> orlyacl.v1.EventSummary + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] 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_orlyacl_v1_types_proto_init() } +func file_orlyacl_v1_types_proto_init() { + if File_orlyacl_v1_types_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_orlyacl_v1_types_proto_rawDesc), len(file_orlyacl_v1_types_proto_rawDesc)), + NumEnums: 0, + NumMessages: 57, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_orlyacl_v1_types_proto_goTypes, + DependencyIndexes: file_orlyacl_v1_types_proto_depIdxs, + MessageInfos: file_orlyacl_v1_types_proto_msgTypes, + }.Build() + File_orlyacl_v1_types_proto = out.File + file_orlyacl_v1_types_proto_goTypes = nil + file_orlyacl_v1_types_proto_depIdxs = nil +} diff --git a/pkg/version/version b/pkg/version/version index 258b831..ec9d004 100644 --- a/pkg/version/version +++ b/pkg/version/version @@ -1 +1 @@ -v0.53.1 +v0.54.0 diff --git a/proto/orlyacl/v1/acl.proto b/proto/orlyacl/v1/acl.proto new file mode 100644 index 0000000..c9e269d --- /dev/null +++ b/proto/orlyacl/v1/acl.proto @@ -0,0 +1,151 @@ +syntax = "proto3"; +package orlyacl.v1; +option go_package = "next.orly.dev/pkg/proto/orlyacl/v1;orlyaclv1"; + +import "orlyacl/v1/types.proto"; + +// ACLService provides access control operations for the Nostr relay +service ACLService { + // Core ACL interface methods + + // GetAccessLevel returns the access level for a pubkey from an IP address + rpc GetAccessLevel(AccessLevelRequest) returns (AccessLevelResponse); + + // CheckPolicy checks if an event passes policy checks + rpc CheckPolicy(PolicyCheckRequest) returns (PolicyCheckResponse); + + // GetACLInfo returns information about the active ACL mode + rpc GetACLInfo(Empty) returns (ACLInfoResponse); + + // GetMode returns the current ACL mode (none/follows/managed/curating) + rpc GetMode(Empty) returns (ModeResponse); + + // Ready checks if the ACL service is ready + rpc Ready(Empty) returns (ReadyResponse); + + // Follows ACL methods + + // GetThrottleDelay returns the progressive throttle delay for a pubkey + rpc GetThrottleDelay(ThrottleDelayRequest) returns (ThrottleDelayResponse); + + // AddFollow adds a pubkey to the followed list + rpc AddFollow(AddFollowRequest) returns (Empty); + + // GetFollowedPubkeys returns all followed pubkeys + rpc GetFollowedPubkeys(Empty) returns (FollowedPubkeysResponse); + + // GetAdminRelays returns the relay URLs from admin kind 10002 events + rpc GetAdminRelays(Empty) returns (AdminRelaysResponse); + + // Managed ACL methods + + // BanPubkey adds a pubkey to the ban list + rpc BanPubkey(BanPubkeyRequest) returns (Empty); + + // UnbanPubkey removes a pubkey from the ban list + rpc UnbanPubkey(PubkeyRequest) returns (Empty); + + // ListBannedPubkeys returns all banned pubkeys + rpc ListBannedPubkeys(Empty) returns (ListBannedPubkeysResponse); + + // AllowPubkey adds a pubkey to the allow list + rpc AllowPubkey(AllowPubkeyRequest) returns (Empty); + + // DisallowPubkey removes a pubkey from the allow list + rpc DisallowPubkey(PubkeyRequest) returns (Empty); + + // ListAllowedPubkeys returns all explicitly allowed pubkeys + rpc ListAllowedPubkeys(Empty) returns (ListAllowedPubkeysResponse); + + // BanEvent adds an event to the ban list + rpc BanEvent(BanEventRequest) returns (Empty); + + // UnbanEvent removes an event from the ban list + rpc UnbanEvent(EventRequest) returns (Empty); + + // ListBannedEvents returns all banned events + rpc ListBannedEvents(Empty) returns (ListBannedEventsResponse); + + // AllowEvent adds an event to the allow list + rpc AllowEvent(BanEventRequest) returns (Empty); + + // DisallowEvent removes an event from the allow list + rpc DisallowEvent(EventRequest) returns (Empty); + + // ListAllowedEvents returns all explicitly allowed events + rpc ListAllowedEvents(Empty) returns (ListAllowedEventsResponse); + + // BlockIP adds an IP to the block list + rpc BlockIP(BlockIPRequest) returns (Empty); + + // UnblockIP removes an IP from the block list + rpc UnblockIP(IPRequest) returns (Empty); + + // ListBlockedIPs returns all blocked IPs + rpc ListBlockedIPs(Empty) returns (ListBlockedIPsResponse); + + // AllowKind adds a kind to the allow list + rpc AllowKind(AllowKindRequest) returns (Empty); + + // DisallowKind removes a kind from the allow list + rpc DisallowKind(KindRequest) returns (Empty); + + // ListAllowedKinds returns all allowed kinds + rpc ListAllowedKinds(Empty) returns (ListAllowedKindsResponse); + + // UpdatePeerAdmins updates the peer relay identity pubkeys + rpc UpdatePeerAdmins(UpdatePeerAdminsRequest) returns (Empty); + + // Curating ACL methods + + // TrustPubkey adds a pubkey to the trusted list + rpc TrustPubkey(TrustPubkeyRequest) returns (Empty); + + // UntrustPubkey removes a pubkey from the trusted list + rpc UntrustPubkey(PubkeyRequest) returns (Empty); + + // ListTrustedPubkeys returns all trusted pubkeys + rpc ListTrustedPubkeys(Empty) returns (ListTrustedPubkeysResponse); + + // BlacklistPubkey adds a pubkey to the blacklist + rpc BlacklistPubkey(BlacklistPubkeyRequest) returns (Empty); + + // UnblacklistPubkey removes a pubkey from the blacklist + rpc UnblacklistPubkey(PubkeyRequest) returns (Empty); + + // ListBlacklistedPubkeys returns all blacklisted pubkeys + rpc ListBlacklistedPubkeys(Empty) returns (ListBlacklistedPubkeysResponse); + + // MarkSpam marks an event as spam + rpc MarkSpam(MarkSpamRequest) returns (Empty); + + // UnmarkSpam removes the spam flag from an event + rpc UnmarkSpam(EventRequest) returns (Empty); + + // ListSpamEvents returns all spam-flagged events + rpc ListSpamEvents(Empty) returns (ListSpamEventsResponse); + + // RateLimitCheck checks if a pubkey/IP can publish (rate limiting) + rpc RateLimitCheck(RateLimitCheckRequest) returns (RateLimitCheckResponse); + + // ProcessConfigEvent processes a curating config event (kind 30078) + rpc ProcessConfigEvent(ConfigEventRequest) returns (Empty); + + // GetCuratingConfig returns the current curating configuration + rpc GetCuratingConfig(Empty) returns (CuratingConfig); + + // IsCuratingConfigured checks if curating mode is configured + rpc IsCuratingConfigured(Empty) returns (BoolResponse); + + // ListUnclassifiedUsers returns users who are not trusted or blacklisted + rpc ListUnclassifiedUsers(PaginationRequest) returns (ListUnclassifiedUsersResponse); + + // GetEventsForPubkey returns events for a specific pubkey + rpc GetEventsForPubkey(GetEventsForPubkeyRequest) returns (EventsForPubkeyResponse); + + // DeleteEventsForPubkey deletes all events for a pubkey + rpc DeleteEventsForPubkey(DeleteEventsForPubkeyRequest) returns (DeleteCountResponse); + + // ScanAllPubkeys scans and indexes all pubkeys in the database + rpc ScanAllPubkeys(Empty) returns (ScanResultResponse); +} diff --git a/proto/orlyacl/v1/types.proto b/proto/orlyacl/v1/types.proto new file mode 100644 index 0000000..daa8a51 --- /dev/null +++ b/proto/orlyacl/v1/types.proto @@ -0,0 +1,292 @@ +syntax = "proto3"; +package orlyacl.v1; +option go_package = "next.orly.dev/pkg/proto/orlyacl/v1;orlyaclv1"; + +import "orlydb/v1/types.proto"; + +// Empty is used for requests/responses with no data +message Empty {} + +// Core ACL Messages + +message AccessLevelRequest { + bytes pubkey = 1; + string address = 2; +} + +message AccessLevelResponse { + string level = 1; // none/read/write/admin/owner/banned/blocked +} + +message ACLInfoResponse { + string name = 1; + string description = 2; + string documentation = 3; +} + +message ModeResponse { + string mode = 1; // none/follows/managed/curating +} + +message ReadyResponse { + bool ready = 1; +} + +message BoolResponse { + bool value = 1; +} + +message PolicyCheckRequest { + orlydb.v1.Event event = 1; +} + +message PolicyCheckResponse { + bool allowed = 1; + string error = 2; +} + +// Follows ACL Messages + +message ThrottleDelayRequest { + bytes pubkey = 1; + string ip = 2; +} + +message ThrottleDelayResponse { + int64 delay_ms = 1; +} + +message AddFollowRequest { + bytes pubkey = 1; +} + +message FollowedPubkeysResponse { + repeated bytes pubkeys = 1; +} + +message AdminRelaysResponse { + repeated string urls = 1; +} + +// Managed ACL Messages + +message PubkeyRequest { + string pubkey = 1; +} + +message IPRequest { + string ip = 1; +} + +message BanPubkeyRequest { + string pubkey = 1; + string reason = 2; +} + +message AllowPubkeyRequest { + string pubkey = 1; + string reason = 2; +} + +message BannedPubkey { + string pubkey = 1; + string reason = 2; + int64 added = 3; +} + +message AllowedPubkey { + string pubkey = 1; + string reason = 2; + int64 added = 3; +} + +message BanEventRequest { + string event_id = 1; + string reason = 2; +} + +message EventRequest { + string event_id = 1; +} + +message BannedEvent { + string event_id = 1; + string reason = 2; + int64 added = 3; +} + +message AllowedEvent { + string event_id = 1; + string reason = 2; + int64 added = 3; +} + +message BlockIPRequest { + string ip = 1; + string reason = 2; +} + +message BlockedIP { + string ip = 1; + string reason = 2; + int64 added = 3; +} + +message AllowKindRequest { + int32 kind = 1; +} + +message KindRequest { + int32 kind = 1; +} + +message UpdatePeerAdminsRequest { + repeated bytes peer_pubkeys = 1; +} + +message ListBannedPubkeysResponse { + repeated BannedPubkey pubkeys = 1; +} + +message ListAllowedPubkeysResponse { + repeated AllowedPubkey pubkeys = 1; +} + +message ListBannedEventsResponse { + repeated BannedEvent events = 1; +} + +message ListAllowedEventsResponse { + repeated AllowedEvent events = 1; +} + +message ListBlockedIPsResponse { + repeated BlockedIP ips = 1; +} + +message ListAllowedKindsResponse { + repeated int32 kinds = 1; +} + +// Curating ACL Messages + +message TrustPubkeyRequest { + string pubkey = 1; + string note = 2; +} + +message BlacklistPubkeyRequest { + string pubkey = 1; + string reason = 2; +} + +message TrustedPubkey { + string pubkey = 1; + string note = 2; + int64 added = 3; +} + +message BlacklistedPubkey { + string pubkey = 1; + string reason = 2; + int64 added = 3; +} + +message MarkSpamRequest { + string event_id = 1; + string pubkey = 2; + string reason = 3; +} + +message SpamEvent { + string event_id = 1; + string pubkey = 2; + string reason = 3; + int64 added = 4; +} + +message RateLimitCheckRequest { + string pubkey = 1; + string ip = 2; +} + +message RateLimitCheckResponse { + bool allowed = 1; + string message = 2; +} + +message ConfigEventRequest { + orlydb.v1.Event event = 1; +} + +message CuratingConfig { + string config_event_id = 1; + string config_pubkey = 2; + int64 configured_at = 3; + int32 daily_limit = 4; + int32 ip_daily_limit = 5; + int32 first_ban_hours = 6; + int32 second_ban_hours = 7; + repeated string kind_categories = 8; + repeated string allowed_ranges = 9; + repeated int32 allowed_kinds = 10; +} + +message UnclassifiedUser { + string pubkey = 1; + int32 event_count = 2; + string first_seen = 3; +} + +message PaginationRequest { + int32 limit = 1; + int32 offset = 2; +} + +message ListTrustedPubkeysResponse { + repeated TrustedPubkey pubkeys = 1; +} + +message ListBlacklistedPubkeysResponse { + repeated BlacklistedPubkey pubkeys = 1; +} + +message ListSpamEventsResponse { + repeated SpamEvent events = 1; +} + +message ListUnclassifiedUsersResponse { + repeated UnclassifiedUser users = 1; + int32 total = 2; +} + +message GetEventsForPubkeyRequest { + string pubkey = 1; + int32 limit = 2; + int32 offset = 3; +} + +message EventSummary { + string id = 1; + uint32 kind = 2; + bytes content = 3; + int64 created_at = 4; +} + +message EventsForPubkeyResponse { + repeated EventSummary events = 1; + int32 total = 2; +} + +message DeleteEventsForPubkeyRequest { + string pubkey = 1; +} + +message DeleteCountResponse { + int32 count = 1; +} + +message ScanResultResponse { + int32 total_pubkeys = 1; + int32 total_events = 2; +}