diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cfea216..1495ee5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: - name: Execute test and upload coverage run: | go version - go test -coverprofile=coverage.txt -covermode=atomic -p 1 ./api ./deliver ./cli ./models + go test -coverprofile=coverage.txt -covermode=atomic -p 1 ./api ./deliver ./control ./models bash <(curl -s https://codecov.io/bash) env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 525834b..79ff001 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,7 @@ COPY . /Activity-Relay RUN mkdir -p /rootfs/usr/bin && \ apk add -U --no-cache git && \ - go build -o /rootfs/usr/bin/relay -ldflags "-X main.version=$(git describe --tags HEAD)" . && \ - go build -o /rootfs/usr/bin/ar-cli -ldflags "-X main.version=$(git describe --tags HEAD)" ./cli + go build -o /rootfs/usr/bin/relay -ldflags "-X main.version=$(git describe --tags HEAD)" . FROM alpine diff --git a/KeyLoader/keyloader.go b/KeyLoader/keyloader.go deleted file mode 100644 index df73c6d..0000000 --- a/KeyLoader/keyloader.go +++ /dev/null @@ -1,21 +0,0 @@ -package keyloader - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "io/ioutil" -) - -func ReadPrivateKeyRSAfromPath(path string) (*rsa.PrivateKey, error) { - file, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - decoded, _ := pem.Decode(file) - priv, err := x509.ParsePKCS1PrivateKey(decoded.Bytes) - if err != nil { - return nil, err - } - return priv, nil -} diff --git a/cli/cli.go b/cli/cli.go deleted file mode 100644 index 818c085..0000000 --- a/cli/cli.go +++ /dev/null @@ -1,87 +0,0 @@ -package main - -import ( - "crypto/rsa" - "fmt" - "net/url" - - "github.com/RichardKnop/machinery/v1" - "github.com/RichardKnop/machinery/v1/config" - "github.com/go-redis/redis" - "github.com/spf13/cobra" - "github.com/spf13/viper" - keyloader "github.com/yukimochi/Activity-Relay/KeyLoader" - "github.com/yukimochi/Activity-Relay/models" -) - -var ( - version string - - // Actor : Relay's Actor - Actor models.Actor - - hostname *url.URL - hostkey *rsa.PrivateKey - relayState models.RelayState - machineryServer *machinery.Server -) - -func initConfig() { - viper.SetConfigName("config") - viper.AddConfigPath(".") - err := viper.ReadInConfig() - if err != nil { - fmt.Println("Config file is not exists. Use environment variables.") - viper.BindEnv("actor_pem") - viper.BindEnv("redis_url") - viper.BindEnv("relay_bind") - viper.BindEnv("relay_domain") - viper.BindEnv("relay_servicename") - } else { - Actor.Summary = viper.GetString("relay_summary") - Actor.Icon = &models.Image{URL: viper.GetString("relay_icon")} - Actor.Image = &models.Image{URL: viper.GetString("relay_image")} - } - Actor.Name = viper.GetString("relay_servicename") - - hostname, err = url.Parse("https://" + viper.GetString("relay_domain")) - if err != nil { - panic(err) - } - hostkey, err := keyloader.ReadPrivateKeyRSAfromPath(viper.GetString("actor_pem")) - if err != nil { - panic(err) - } - redisOption, err := redis.ParseURL(viper.GetString("redis_url")) - if err != nil { - panic(err) - } - redisClient := redis.NewClient(redisOption) - relayState = models.NewState(redisClient, true) - var machineryConfig = &config.Config{ - Broker: viper.GetString("redis_url"), - DefaultQueue: "relay", - ResultBackend: viper.GetString("redis_url"), - ResultsExpireIn: 5, - } - machineryServer, err = machinery.NewServer(machineryConfig) - if err != nil { - panic(err) - } - - Actor.GenerateSelfKey(hostname, &hostkey.PublicKey) -} - -func buildNewCmd() *cobra.Command { - var app = &cobra.Command{} - app.AddCommand(domainCmdInit()) - app.AddCommand(followCmdInit()) - app.AddCommand(configCmdInit()) - return app -} - -func main() { - initConfig() - var app = buildNewCmd() - app.Execute() -} diff --git a/cli/cli_test.go b/cli/cli_test.go deleted file mode 100644 index 63dd6d3..0000000 --- a/cli/cli_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "os" - "testing" - - "github.com/spf13/viper" - "github.com/yukimochi/Activity-Relay/models" -) - -func TestMain(m *testing.M) { - viper.Set("actor_pem", "../misc/testKey.pem") - viper.Set("relay_domain", "relay.yukimochi.example.org") - initConfig() - relayState = models.NewState(relayState.RedisClient, false) - relayState.RedisClient.FlushAll().Result() - - code := m.Run() - os.Exit(code) -} diff --git a/cli/config.go b/control/config.go similarity index 92% rename from cli/config.go rename to control/config.go index 2041347..ca9d404 100644 --- a/cli/config.go +++ b/control/config.go @@ -1,4 +1,4 @@ -package main +package control import ( "encoding/json" @@ -27,7 +27,9 @@ func configCmdInit() *cobra.Command { Use: "list", Short: "List all relay configration", Long: "List all relay configration.", - Run: listConfig, + Run: func(cmd *cobra.Command, args []string) { + initProxy(listConfig, cmd, args) + }, } config.AddCommand(configList) @@ -35,7 +37,9 @@ func configCmdInit() *cobra.Command { Use: "export", Short: "Export all relay information", Long: "Export all relay information by JSON format.", - Run: exportConfig, + Run: func(cmd *cobra.Command, args []string) { + initProxy(exportConfig, cmd, args) + }, } config.AddCommand(configExport) @@ -43,7 +47,9 @@ func configCmdInit() *cobra.Command { Use: "import [flags]", Short: "Import all relay information", Long: "Import all relay information from JSON file.", - Run: importConfig, + Run: func(cmd *cobra.Command, args []string) { + initProxy(importConfig, cmd, args) + }, } configImport.Flags().String("json", "", "JSON file-path") configImport.MarkFlagRequired("json") @@ -60,7 +66,9 @@ func configCmdInit() *cobra.Command { - create-as-announce Enable announce activity instead of relay create activity (not recommend)`, Args: cobra.MinimumNArgs(1), - RunE: configEnable, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(configEnable, cmd, args) + }, } configEnable.Flags().BoolP("disable", "d", false, "Disable configration instead of Enable") config.AddCommand(configEnable) diff --git a/cli/config_test.go b/control/config_test.go similarity index 78% rename from cli/config_test.go rename to control/config_test.go index c18e8e5..c9cb99c 100644 --- a/cli/config_test.go +++ b/control/config_test.go @@ -1,4 +1,4 @@ -package main +package control import ( "bytes" @@ -11,16 +11,16 @@ import ( func TestServiceBlock(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "enable", "service-block"}) + app.SetArgs([]string{"enable", "service-block"}) app.Execute() relayState.Load() if !relayState.RelayConfig.BlockService { t.Fatalf("Not Enabled Blocking feature for service-type actor") } - app.SetArgs([]string{"config", "enable", "-d", "service-block"}) + app.SetArgs([]string{"enable", "-d", "service-block"}) app.Execute() relayState.Load() if relayState.RelayConfig.BlockService { @@ -31,16 +31,16 @@ func TestServiceBlock(t *testing.T) { func TestManuallyAccept(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "enable", "manually-accept"}) + app.SetArgs([]string{"enable", "manually-accept"}) app.Execute() relayState.Load() if !relayState.RelayConfig.ManuallyAccept { t.Fatalf("Not Enabled Manually accept follow-request feature") } - app.SetArgs([]string{"config", "enable", "-d", "manually-accept"}) + app.SetArgs([]string{"enable", "-d", "manually-accept"}) app.Execute() relayState.Load() if relayState.RelayConfig.ManuallyAccept { @@ -51,16 +51,16 @@ func TestManuallyAccept(t *testing.T) { func TestCreateAsAnnounce(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "enable", "create-as-announce"}) + app.SetArgs([]string{"enable", "create-as-announce"}) app.Execute() relayState.Load() if !relayState.RelayConfig.CreateAsAnnounce { t.Fatalf("Enable announce activity instead of relay create activity") } - app.SetArgs([]string{"config", "enable", "-d", "create-as-announce"}) + app.SetArgs([]string{"enable", "-d", "create-as-announce"}) app.Execute() relayState.Load() if relayState.RelayConfig.CreateAsAnnounce { @@ -71,11 +71,11 @@ func TestCreateAsAnnounce(t *testing.T) { func TestInvalidConfig(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"config", "enable", "hoge"}) + app.SetArgs([]string{"enable", "hoge"}) app.Execute() output := buffer.String() @@ -87,11 +87,11 @@ func TestInvalidConfig(t *testing.T) { func TestListConfig(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"config", "list"}) + app.SetArgs([]string{"list"}) app.Execute() output := buffer.String() @@ -116,11 +116,11 @@ func TestListConfig(t *testing.T) { func TestExportConfig(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"config", "export"}) + app.SetArgs([]string{"export"}) app.Execute() file, err := os.Open("../misc/blankConfig.json") @@ -137,16 +137,16 @@ func TestExportConfig(t *testing.T) { func TestImportConfig(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"config", "export"}) + app.SetArgs([]string{"export"}) app.Execute() file, err := os.Open("../misc/exampleConfig.json") diff --git a/control/control.go b/control/control.go new file mode 100644 index 0000000..8f02494 --- /dev/null +++ b/control/control.go @@ -0,0 +1,90 @@ +package control + +import ( + "fmt" + "os" + + "github.com/RichardKnop/machinery/v1" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/yukimochi/Activity-Relay/models" +) + +var ( + globalConfig *models.RelayConfig + + initProxy = initializeProxy + initProxyE = initializeProxyE + + // Actor : Relay's Actor + Actor models.Actor + + relayState models.RelayState + machineryServer *machinery.Server +) + +func BuildCommand(command *cobra.Command) { + command.AddCommand(configCmdInit()) + command.AddCommand(domainCmdInit()) + command.AddCommand(followCmdInit()) +} + +func initializeProxy(function func(cmd *cobra.Command, args []string), cmd *cobra.Command, args []string) { + initConfig(cmd) + function(cmd, args) +} + +func initializeProxyE(function func(cmd *cobra.Command, args []string) error, cmd *cobra.Command, args []string) error { + initConfig(cmd) + return function(cmd, args) +} + +func initConfig(cmd *cobra.Command) error { + var err error + + configPath := cmd.Flag("config").Value.String() + file, err := os.Open(configPath) + defer file.Close() + + if err == nil { + viper.SetConfigType("yaml") + viper.ReadConfig(file) + } else { + fmt.Fprintln(os.Stderr, "Config file not exist. Use environment variables.") + + viper.BindEnv("ACTOR_PEM") + viper.BindEnv("REDIS_URL") + viper.BindEnv("RELAY_BIND") + viper.BindEnv("RELAY_DOMAIN") + viper.BindEnv("RELAY_SERVICENAME") + viper.BindEnv("JOB_CONCURRENCY") + viper.BindEnv("RELAY_SUMMARY") + viper.BindEnv("RELAY_ICON") + viper.BindEnv("RELAY_IMAGE") + } + + globalConfig, err = models.NewRelayConfig() + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + + return nil +} + +func initialize(globalconfig *models.RelayConfig) error { + var err error + + redisClient := globalConfig.RedisClient() + relayState = models.NewState(redisClient, true) + relayState.ListenNotify(nil) + + machineryServer, err = models.NewMachineryServer(globalConfig) + if err != nil { + return err + } + + Actor = models.NewActivityPubActorFromSelfKey(globalConfig) + + return nil +} diff --git a/control/control_test.go b/control/control_test.go new file mode 100644 index 0000000..2b8d693 --- /dev/null +++ b/control/control_test.go @@ -0,0 +1,52 @@ +package control + +import ( + "fmt" + "os" + "testing" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/yukimochi/Activity-Relay/models" +) + +func TestMain(m *testing.M) { + var err error + + testConfigPath := "../misc/config.yml" + file, _ := os.Open(testConfigPath) + defer file.Close() + + viper.SetConfigType("yaml") + viper.ReadConfig(file) + viper.Set("ACTOR_PEM", "../misc/testKey.pem") + viper.BindEnv("REDIS_URL") + + globalConfig, err = models.NewRelayConfig() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + + err = initialize(globalConfig) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + relayState = models.NewState(globalConfig.RedisClient(), false) + relayState.RedisClient.FlushAll().Result() + + initProxy = emptyProxy + initProxyE = emptyProxyE + + code := m.Run() + os.Exit(code) +} + +func emptyProxy(function func(cmd *cobra.Command, args []string), cmd *cobra.Command, args []string) { + function(cmd, args) +} + +func emptyProxyE(function func(cmd *cobra.Command, args []string) error, cmd *cobra.Command, args []string) error { + return function(cmd, args) +} diff --git a/cli/domain.go b/control/domain.go similarity index 89% rename from cli/domain.go rename to control/domain.go index b86ba26..f8220e6 100644 --- a/cli/domain.go +++ b/control/domain.go @@ -1,4 +1,4 @@ -package main +package control import ( "encoding/json" @@ -19,7 +19,9 @@ func domainCmdInit() *cobra.Command { Use: "list [flags]", Short: "List domain", Long: "List domain which filtered given type.", - RunE: listDomains, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(listDomains, cmd, args) + }, } domainList.Flags().StringP("type", "t", "subscriber", "domain type [subscriber,limited,blocked]") domain.AddCommand(domainList) @@ -29,7 +31,9 @@ func domainCmdInit() *cobra.Command { Short: "Set or unset domain as limited or blocked", Long: "Set or unset domain as limited or blocked.", Args: cobra.MinimumNArgs(1), - RunE: setDomainType, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(setDomainType, cmd, args) + }, } domainSet.Flags().StringP("type", "t", "", "Apply domain type [limited,blocked]") domainSet.MarkFlagRequired("type") @@ -40,7 +44,9 @@ func domainCmdInit() *cobra.Command { Use: "unfollow [flags]", Short: "Send Unfollow request for given domains", Long: "Send unfollow request for given domains.", - RunE: unfollowDomains, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(unfollowDomains, cmd, args) + }, } domain.AddCommand(domainUnfollow) @@ -56,7 +62,7 @@ func createUnfollowRequestResponse(subscription models.Subscription) error { Object: "https://www.w3.org/ns/activitystreams#Public", } - resp := activity.GenerateResponse(hostname, "Reject") + resp := activity.GenerateResponse(globalConfig.ServerHostname(), "Reject") jsonData, _ := json.Marshal(&resp) pushRegistorJob(subscription.InboxURL, jsonData) diff --git a/cli/domain_test.go b/control/domain_test.go similarity index 67% rename from cli/domain_test.go rename to control/domain_test.go index 18e7279..0a9e751 100644 --- a/cli/domain_test.go +++ b/control/domain_test.go @@ -1,4 +1,4 @@ -package main +package control import ( "bytes" @@ -9,15 +9,16 @@ import ( func TestListDomainSubscriber(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app := configCmdInit() + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) - app.SetOutput(buffer) - app.SetArgs([]string{"domain", "list"}) + app = domainCmdInit() + app.SetOutput(buffer) + app.SetArgs([]string{"list"}) app.Execute() output := buffer.String() @@ -33,16 +34,17 @@ Total : 1 func TestListDomainLimited(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) - app.SetOutput(buffer) - app.SetArgs([]string{"domain", "list", "-t", "limited"}) + app = domainCmdInit() + app.SetOutput(buffer) + app.SetArgs([]string{"list", "-t", "limited"}) app.Execute() output := buffer.String() @@ -58,16 +60,17 @@ Total : 1 func TestListDomainBlocked(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) - app.SetOutput(buffer) - app.SetArgs([]string{"domain", "list", "-t", "blocked"}) + app = domainCmdInit() + app.SetOutput(buffer) + app.SetArgs([]string{"list", "-t", "blocked"}) app.Execute() output := buffer.String() @@ -83,9 +86,9 @@ Total : 1 func TestSetDomainBlocked(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := domainCmdInit() - app.SetArgs([]string{"domain", "set", "-t", "blocked", "testdomain.example.jp"}) + app.SetArgs([]string{"set", "-t", "blocked", "testdomain.example.jp"}) app.Execute() relayState.Load() @@ -104,9 +107,9 @@ func TestSetDomainBlocked(t *testing.T) { func TestSetDomainLimited(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := domainCmdInit() - app.SetArgs([]string{"domain", "set", "-t", "limited", "testdomain.example.jp"}) + app.SetArgs([]string{"set", "-t", "limited", "testdomain.example.jp"}) app.Execute() relayState.Load() @@ -125,12 +128,13 @@ func TestSetDomainLimited(t *testing.T) { func TestUnsetDomainBlocked(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() - app.SetArgs([]string{"domain", "set", "-t", "blocked", "-u", "blockedDomain.example.jp"}) + app = domainCmdInit() + app.SetArgs([]string{"set", "-t", "blocked", "-u", "blockedDomain.example.jp"}) app.Execute() relayState.Load() @@ -149,12 +153,13 @@ func TestUnsetDomainBlocked(t *testing.T) { func TestUnsetDomainLimited(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() - app.SetArgs([]string{"domain", "set", "-t", "limited", "-u", "limitedDomain.example.jp"}) + app = domainCmdInit() + app.SetArgs([]string{"set", "-t", "limited", "-u", "limitedDomain.example.jp"}) app.Execute() relayState.Load() @@ -173,16 +178,17 @@ func TestUnsetDomainLimited(t *testing.T) { func TestSetDomainInvalid(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) - app.SetOutput(buffer) - app.SetArgs([]string{"domain", "set", "-t", "hoge", "hoge.example.jp"}) + app = domainCmdInit() + app.SetOutput(buffer) + app.SetArgs([]string{"set", "-t", "hoge", "hoge.example.jp"}) app.Execute() output := buffer.String() @@ -194,12 +200,13 @@ func TestSetDomainInvalid(t *testing.T) { func TestUnfollowDomain(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() - app.SetArgs([]string{"domain", "unfollow", "subscription.example.jp"}) + app = domainCmdInit() + app.SetArgs([]string{"unfollow", "subscription.example.jp"}) app.Execute() relayState.Load() @@ -218,16 +225,17 @@ func TestUnfollowDomain(t *testing.T) { func TestInvalidUnfollowDomain(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() relayState.Load() buffer := new(bytes.Buffer) - app.SetOutput(buffer) - app.SetArgs([]string{"domain", "unfollow", "unknown.tld"}) + app = domainCmdInit() + app.SetOutput(buffer) + app.SetArgs([]string{"unfollow", "unknown.tld"}) app.Execute() output := buffer.String() diff --git a/cli/follow.go b/control/follow.go similarity index 87% rename from cli/follow.go rename to control/follow.go index 6237eac..46b5eaf 100644 --- a/cli/follow.go +++ b/control/follow.go @@ -1,4 +1,4 @@ -package main +package control import ( "encoding/json" @@ -23,7 +23,9 @@ func followCmdInit() *cobra.Command { Use: "list", Short: "List follow request", Long: "List follow request.", - RunE: listFollows, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(listFollows, cmd, args) + }, } follow.AddCommand(followList) @@ -32,7 +34,9 @@ func followCmdInit() *cobra.Command { Short: "Accept follow request", Long: "Accept follow request by domain.", Args: cobra.MinimumNArgs(1), - RunE: acceptFollow, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(acceptFollow, cmd, args) + }, } follow.AddCommand(followAccept) @@ -41,7 +45,9 @@ func followCmdInit() *cobra.Command { Short: "Reject follow request", Long: "Reject follow request by domain.", Args: cobra.MinimumNArgs(1), - RunE: rejectFollow, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(rejectFollow, cmd, args) + }, } follow.AddCommand(followReject) @@ -49,7 +55,9 @@ func followCmdInit() *cobra.Command { Use: "update", Short: "Update actor object", Long: "Update actor object for whole subscribers.", - RunE: updateActor, + RunE: func(cmd *cobra.Command, args []string) error { + return initProxyE(updateActor, cmd, args) + }, } follow.AddCommand(updateActor) @@ -92,7 +100,7 @@ func createFollowRequestResponse(domain string, response string) error { Object: data["object"], } - resp := activity.GenerateResponse(hostname, response) + resp := activity.GenerateResponse(globalConfig.ServerHostname(), response) jsonData, err := json.Marshal(&resp) if err != nil { return err @@ -114,8 +122,8 @@ func createFollowRequestResponse(domain string, response string) error { func createUpdateActorActivity(subscription models.Subscription) error { activity := models.Activity{ Context: []string{"https://www.w3.org/ns/activitystreams"}, - ID: hostname.String() + "/activities/" + uuid.NewV4().String(), - Actor: hostname.String() + "/actor", + ID: globalConfig.ServerHostname().String() + "/activities/" + uuid.NewV4().String(), + Actor: globalConfig.ServerHostname().String() + "/actor", Type: "Update", To: []string{"https://www.w3.org/ns/activitystreams#Public"}, Object: Actor, diff --git a/cli/follow_test.go b/control/follow_test.go similarity index 77% rename from cli/follow_test.go rename to control/follow_test.go index f61b9db..d9940a1 100644 --- a/cli/follow_test.go +++ b/control/follow_test.go @@ -1,4 +1,4 @@ -package main +package control import ( "bytes" @@ -9,7 +9,7 @@ import ( func TestListFollows(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := followCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) @@ -19,10 +19,10 @@ func TestListFollows(t *testing.T) { "activity_id": "https://example.com/UUID", "type": "Follow", "actor": "https://example.com/user/example", - "object": "https://" + hostname.Host + "/actor", + "object": "https://" + globalConfig.ServerHostname().Host + "/actor", }) - app.SetArgs([]string{"follow", "list"}) + app.SetArgs([]string{"list"}) app.Execute() output := buffer.String() @@ -38,17 +38,17 @@ Total : 1 func TestAcceptFollow(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := followCmdInit() relayState.RedisClient.HMSet("relay:pending:example.com", map[string]interface{}{ "inbox_url": "https://example.com/inbox", "activity_id": "https://example.com/UUID", "type": "Follow", "actor": "https://example.com/user/example", - "object": "https://" + hostname.Host + "/actor", + "object": "https://" + globalConfig.ServerHostname().Host + "/actor", }) - app.SetArgs([]string{"follow", "accept", "example.com"}) + app.SetArgs([]string{"accept", "example.com"}) app.Execute() valid, _ := relayState.RedisClient.Exists("relay:pending:example.com").Result() @@ -65,17 +65,17 @@ func TestAcceptFollow(t *testing.T) { func TestRejectFollow(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := followCmdInit() relayState.RedisClient.HMSet("relay:pending:example.com", map[string]interface{}{ "inbox_url": "https://example.com/inbox", "activity_id": "https://example.com/UUID", "type": "Follow", "actor": "https://example.com/user/example", - "object": "https://" + hostname.Host + "/actor", + "object": "https://" + globalConfig.ServerHostname().Host + "/actor", }) - app.SetArgs([]string{"follow", "reject", "example.com"}) + app.SetArgs([]string{"reject", "example.com"}) app.Execute() valid, _ := relayState.RedisClient.Exists("relay:pending:example.com").Result() @@ -92,12 +92,12 @@ func TestRejectFollow(t *testing.T) { func TestInvalidFollow(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := followCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"follow", "accept", "unknown.tld"}) + app.SetArgs([]string{"accept", "unknown.tld"}) app.Execute() output := buffer.String() @@ -109,12 +109,12 @@ func TestInvalidFollow(t *testing.T) { func TestInvalidRejectFollow(t *testing.T) { relayState.RedisClient.FlushAll().Result() - app := buildNewCmd() + app := followCmdInit() buffer := new(bytes.Buffer) app.SetOutput(buffer) - app.SetArgs([]string{"follow", "reject", "unknown.tld"}) + app.SetArgs([]string{"reject", "unknown.tld"}) app.Execute() output := buffer.String() @@ -124,11 +124,13 @@ func TestInvalidRejectFollow(t *testing.T) { } func TestCreateUpdateActorActivity(t *testing.T) { - app := buildNewCmd() + app := configCmdInit() - app.SetArgs([]string{"config", "import", "--json", "../misc/exampleConfig.json"}) + app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"}) app.Execute() - app.SetArgs([]string{"follow", "update"}) + app = followCmdInit() + + app.SetArgs([]string{"update"}) app.Execute() } diff --git a/cli/contain.go b/control/utils.go similarity index 96% rename from cli/contain.go rename to control/utils.go index e995587..fe05e1f 100644 --- a/cli/contain.go +++ b/control/utils.go @@ -1,4 +1,4 @@ -package main +package control import "github.com/yukimochi/Activity-Relay/models" diff --git a/cli/contain_test.go b/control/utils_test.go similarity index 97% rename from cli/contain_test.go rename to control/utils_test.go index 444f201..6ca9cc9 100644 --- a/cli/contain_test.go +++ b/control/utils_test.go @@ -1,4 +1,4 @@ -package main +package control import "testing" diff --git a/main.go b/main.go index 900e050..36fc07c 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ API Server ./Activity-Relay -c server Job Worker ./Activity-Relay -c worker +CLI Management Utility + ./Activity-Relay -c control Config @@ -44,6 +46,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/yukimochi/Activity-Relay/api" + "github.com/yukimochi/Activity-Relay/control" "github.com/yukimochi/Activity-Relay/deliver" "github.com/yukimochi/Activity-Relay/models" ) @@ -67,7 +70,7 @@ func buildCommand() *cobra.Command { Short: "Activity-Relay API Server", Long: "Activity-Relay API Server is providing WebFinger API, ActivityPub inbox", RunE: func(cmd *cobra.Command, args []string) error { - initConfig(cmd, args) + initConfig(cmd) fmt.Println(globalConfig.DumpWelcomeMessage("API Server", version)) err := api.Entrypoint(globalConfig, version) if err != nil { @@ -83,7 +86,7 @@ func buildCommand() *cobra.Command { Short: "Activity-Relay Job Worker", Long: "Activity-Relay Job Worker is providing ActivityPub Activity deliverer", RunE: func(cmd *cobra.Command, args []string) error { - initConfig(cmd, args) + initConfig(cmd) fmt.Println(globalConfig.DumpWelcomeMessage("Job Worker", version)) err := deliver.Entrypoint(globalConfig, version) if err != nil { @@ -94,17 +97,25 @@ func buildCommand() *cobra.Command { }, } + var command = &cobra.Command{ + Use: "control", + Short: "Activity-Relay CLI", + Long: "Activity-Relay CLI Management Utility", + } + control.BuildCommand(command) + var app = &cobra.Command{ Short: "YUKIMOCHI Activity-Relay", Long: "YUKIMOCHI Activity-Relay - ActivityPub Relay Server", } app.AddCommand(server) app.AddCommand(worker) + app.AddCommand(command) return app } -func initConfig(cmd *cobra.Command, args []string) { +func initConfig(cmd *cobra.Command) { configPath := cmd.Flag("config").Value.String() file, err := os.Open(configPath) defer file.Close() diff --git a/readme.md b/readme.md index dc52f01..130fad8 100644 --- a/readme.md +++ b/readme.md @@ -20,13 +20,29 @@ - [Redis](https://github.com/antirez/redis) -## Installation Manual +## Run -See [GitHub wiki](https://github.com/yukimochi/Activity-Relay/wiki) +### API Server -## Configration +```bash +relay -c server +``` -### `config.yml` +### Job Worker + +```bash +relay -c worker +``` + +### CLI Management Utility + +```bash +relay -c control +``` + +## Config + +### YAML Format ```yaml config.yml ACTOR_PEM: /actor.pem @@ -42,7 +58,7 @@ JOB_CONCURRENCY: 50 # RELAY_IMAGE: https:// ``` -### `Environment Variable` +### Environment Variable This is **Optional** : When `config.yml` not exists, use environment variable. @@ -57,4 +73,17 @@ JOB_CONCURRENCY: 50 - RELAY_IMAGE ## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fyukimochi%2FActivity-Relay.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fyukimochi%2FActivity-Relay?ref=badge_large) \ No newline at end of file +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fyukimochi%2FActivity-Relay.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fyukimochi%2FActivity-Relay?ref=badge_large) + +## Project Sponsors + +Thank you for your support. + +### Monthly Donation + +**[My Doner List](https://relay.toot.yukimochi.jp#patreon-list)** + +#### Donation Platform + - [Patreon](https://www.patreon.com/yukimochi) + - [pixiv fanbox](https://yukimochi.fanbox.cc) + - [fantia](https://fantia.jp/fanclubs/11264)