Mono-binarify for control.
This commit is contained in:
173
control/config.go
Normal file
173
control/config.go
Normal file
@ -0,0 +1,173 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yukimochi/Activity-Relay/models"
|
||||
)
|
||||
|
||||
const (
|
||||
BlockService models.Config = iota
|
||||
ManuallyAccept
|
||||
CreateAsAnnounce
|
||||
)
|
||||
|
||||
func configCmdInit() *cobra.Command {
|
||||
var config = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage configuration for relay",
|
||||
Long: "Enable/disable relay costomize and import/export relay database.",
|
||||
}
|
||||
|
||||
var configList = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all relay configration",
|
||||
Long: "List all relay configration.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
initProxy(listConfig, cmd, args)
|
||||
},
|
||||
}
|
||||
config.AddCommand(configList)
|
||||
|
||||
var configExport = &cobra.Command{
|
||||
Use: "export",
|
||||
Short: "Export all relay information",
|
||||
Long: "Export all relay information by JSON format.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
initProxy(exportConfig, cmd, args)
|
||||
},
|
||||
}
|
||||
config.AddCommand(configExport)
|
||||
|
||||
var configImport = &cobra.Command{
|
||||
Use: "import [flags]",
|
||||
Short: "Import all relay information",
|
||||
Long: "Import all relay information from JSON file.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
initProxy(importConfig, cmd, args)
|
||||
},
|
||||
}
|
||||
configImport.Flags().String("json", "", "JSON file-path")
|
||||
configImport.MarkFlagRequired("json")
|
||||
config.AddCommand(configImport)
|
||||
|
||||
var configEnable = &cobra.Command{
|
||||
Use: "enable",
|
||||
Short: "Enable/disable relay configration",
|
||||
Long: `Enable or disable relay configration.
|
||||
- service-block
|
||||
Blocking feature for service-type actor.
|
||||
- manually-accept
|
||||
Enable manually accept follow request.
|
||||
- create-as-announce
|
||||
Enable announce activity instead of relay create activity (not recommend)`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
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)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func configEnable(cmd *cobra.Command, args []string) error {
|
||||
disable := cmd.Flag("disable").Value.String() == "true"
|
||||
for _, config := range args {
|
||||
switch config {
|
||||
case "service-block":
|
||||
if disable {
|
||||
relayState.SetConfig(BlockService, false)
|
||||
cmd.Println("Blocking for service-type actor is Disabled.")
|
||||
} else {
|
||||
relayState.SetConfig(BlockService, true)
|
||||
cmd.Println("Blocking for service-type actor is Enabled.")
|
||||
}
|
||||
case "manually-accept":
|
||||
if disable {
|
||||
relayState.SetConfig(ManuallyAccept, false)
|
||||
cmd.Println("Manually accept follow-request is Disabled.")
|
||||
} else {
|
||||
relayState.SetConfig(ManuallyAccept, true)
|
||||
cmd.Println("Manually accept follow-request is Enabled.")
|
||||
}
|
||||
case "create-as-announce":
|
||||
if disable {
|
||||
relayState.SetConfig(CreateAsAnnounce, false)
|
||||
cmd.Println("Announce activity instead of relay create activity is Disabled.")
|
||||
} else {
|
||||
relayState.SetConfig(CreateAsAnnounce, true)
|
||||
cmd.Println("Announce activity instead of relay create activity is Enabled.")
|
||||
}
|
||||
default:
|
||||
cmd.Println("Invalid config given")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listConfig(cmd *cobra.Command, args []string) {
|
||||
cmd.Println("Blocking for service-type actor : ", relayState.RelayConfig.BlockService)
|
||||
cmd.Println("Manually accept follow-request : ", relayState.RelayConfig.ManuallyAccept)
|
||||
cmd.Println("Announce activity instead of relay create activity : ", relayState.RelayConfig.CreateAsAnnounce)
|
||||
}
|
||||
|
||||
func exportConfig(cmd *cobra.Command, args []string) {
|
||||
jsonData, _ := json.Marshal(&relayState)
|
||||
cmd.Println(string(jsonData))
|
||||
}
|
||||
|
||||
func importConfig(cmd *cobra.Command, args []string) {
|
||||
file, err := os.Open(cmd.Flag("json").Value.String())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
jsonData, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
var data models.RelayState
|
||||
err = json.Unmarshal(jsonData, &data)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return
|
||||
}
|
||||
|
||||
if data.RelayConfig.BlockService {
|
||||
relayState.SetConfig(BlockService, true)
|
||||
cmd.Println("Blocking for service-type actor is Enabled.")
|
||||
}
|
||||
if data.RelayConfig.ManuallyAccept {
|
||||
relayState.SetConfig(ManuallyAccept, true)
|
||||
cmd.Println("Manually accept follow-request is Enabled.")
|
||||
}
|
||||
if data.RelayConfig.CreateAsAnnounce {
|
||||
relayState.SetConfig(CreateAsAnnounce, true)
|
||||
cmd.Println("Announce activity instead of relay create activity is Enabled.")
|
||||
}
|
||||
for _, LimitedDomain := range data.LimitedDomains {
|
||||
relayState.SetLimitedDomain(LimitedDomain, true)
|
||||
cmd.Println("Set [" + LimitedDomain + "] as limited domain")
|
||||
}
|
||||
for _, BlockedDomain := range data.BlockedDomains {
|
||||
relayState.SetBlockedDomain(BlockedDomain, true)
|
||||
cmd.Println("Set [" + BlockedDomain + "] as blocked domain")
|
||||
}
|
||||
for _, Subscription := range data.Subscriptions {
|
||||
relayState.AddSubscription(models.Subscription{
|
||||
Domain: Subscription.Domain,
|
||||
InboxURL: Subscription.InboxURL,
|
||||
ActivityID: Subscription.ActivityID,
|
||||
ActorID: Subscription.ActorID,
|
||||
})
|
||||
cmd.Println("Regist [" + Subscription.Domain + "] as subscriber")
|
||||
}
|
||||
}
|
161
control/config_test.go
Normal file
161
control/config_test.go
Normal file
@ -0,0 +1,161 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServiceBlock(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
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{"enable", "-d", "service-block"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
if relayState.RelayConfig.BlockService {
|
||||
t.Fatalf("Not Disabled Blocking feature for service-type actor")
|
||||
}
|
||||
}
|
||||
|
||||
func TestManuallyAccept(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
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{"enable", "-d", "manually-accept"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
if relayState.RelayConfig.ManuallyAccept {
|
||||
t.Fatalf("Not Disabled Manually accept follow-request feature")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAsAnnounce(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
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{"enable", "-d", "create-as-announce"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
if relayState.RelayConfig.CreateAsAnnounce {
|
||||
t.Fatalf("Enable announce activity instead of relay create activity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidConfig(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"enable", "hoge"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != "Invalid config given" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListConfig(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"list"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
for _, row := range strings.Split(output, "\n") {
|
||||
switch strings.Split(row, ":")[0] {
|
||||
case "Blocking for service-type actor ":
|
||||
if strings.Split(row, ":")[1] == " true" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
case "Manually accept follow-request ":
|
||||
if strings.Split(row, ":")[1] == " true" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
case "Announce activity instead of relay create activity ":
|
||||
if strings.Split(row, ":")[1] == " true" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportConfig(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"export"})
|
||||
app.Execute()
|
||||
|
||||
file, err := os.Open("../misc/blankConfig.json")
|
||||
if err != nil {
|
||||
t.Fatalf("Test resource fetch error.")
|
||||
}
|
||||
jsonData, err := ioutil.ReadAll(file)
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != string(jsonData) {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportConfig(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"export"})
|
||||
app.Execute()
|
||||
|
||||
file, err := os.Open("../misc/exampleConfig.json")
|
||||
if err != nil {
|
||||
t.Fatalf("Test resource fetch error.")
|
||||
}
|
||||
jsonData, err := ioutil.ReadAll(file)
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != string(jsonData) {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
90
control/control.go
Normal file
90
control/control.go
Normal file
@ -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
|
||||
}
|
52
control/control_test.go
Normal file
52
control/control_test.go
Normal file
@ -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)
|
||||
}
|
139
control/domain.go
Normal file
139
control/domain.go
Normal file
@ -0,0 +1,139 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yukimochi/Activity-Relay/models"
|
||||
)
|
||||
|
||||
func domainCmdInit() *cobra.Command {
|
||||
var domain = &cobra.Command{
|
||||
Use: "domain",
|
||||
Short: "Manage subscriber domain",
|
||||
Long: "List all subscriber, set/unset domain as limited or blocked and undo subscribe domain.",
|
||||
}
|
||||
|
||||
var domainList = &cobra.Command{
|
||||
Use: "list [flags]",
|
||||
Short: "List domain",
|
||||
Long: "List domain which filtered given type.",
|
||||
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)
|
||||
|
||||
var domainSet = &cobra.Command{
|
||||
Use: "set [flags]",
|
||||
Short: "Set or unset domain as limited or blocked",
|
||||
Long: "Set or unset domain as limited or blocked.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
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")
|
||||
domainSet.Flags().BoolP("undo", "u", false, "Unset domain as limited or blocked")
|
||||
domain.AddCommand(domainSet)
|
||||
|
||||
var domainUnfollow = &cobra.Command{
|
||||
Use: "unfollow [flags]",
|
||||
Short: "Send Unfollow request for given domains",
|
||||
Long: "Send unfollow request for given domains.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initProxyE(unfollowDomains, cmd, args)
|
||||
},
|
||||
}
|
||||
domain.AddCommand(domainUnfollow)
|
||||
|
||||
return domain
|
||||
}
|
||||
|
||||
func createUnfollowRequestResponse(subscription models.Subscription) error {
|
||||
activity := models.Activity{
|
||||
Context: []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"},
|
||||
ID: subscription.ActivityID,
|
||||
Actor: subscription.ActorID,
|
||||
Type: "Follow",
|
||||
Object: "https://www.w3.org/ns/activitystreams#Public",
|
||||
}
|
||||
|
||||
resp := activity.GenerateResponse(globalConfig.ServerHostname(), "Reject")
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
pushRegistorJob(subscription.InboxURL, jsonData)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listDomains(cmd *cobra.Command, args []string) error {
|
||||
var domains []string
|
||||
switch cmd.Flag("type").Value.String() {
|
||||
case "limited":
|
||||
cmd.Println(" - Limited domain :")
|
||||
domains = relayState.LimitedDomains
|
||||
case "blocked":
|
||||
cmd.Println(" - Blocked domain :")
|
||||
domains = relayState.BlockedDomains
|
||||
default:
|
||||
cmd.Println(" - Subscriber domain :")
|
||||
temp := relayState.Subscriptions
|
||||
for _, domain := range temp {
|
||||
domains = append(domains, domain.Domain)
|
||||
}
|
||||
}
|
||||
for _, domain := range domains {
|
||||
cmd.Println(domain)
|
||||
}
|
||||
cmd.Println(fmt.Sprintf("Total : %d", len(domains)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDomainType(cmd *cobra.Command, args []string) error {
|
||||
undo := cmd.Flag("undo").Value.String() == "true"
|
||||
switch cmd.Flag("type").Value.String() {
|
||||
case "limited":
|
||||
for _, domain := range args {
|
||||
relayState.SetLimitedDomain(domain, !undo)
|
||||
if undo {
|
||||
cmd.Println("Unset [" + domain + "] as limited domain")
|
||||
} else {
|
||||
cmd.Println("Set [" + domain + "] as limited domain")
|
||||
}
|
||||
}
|
||||
case "blocked":
|
||||
for _, domain := range args {
|
||||
relayState.SetBlockedDomain(domain, !undo)
|
||||
if undo {
|
||||
cmd.Println("Unset [" + domain + "] as blocked domain")
|
||||
} else {
|
||||
cmd.Println("Set [" + domain + "] as blocked domain")
|
||||
}
|
||||
}
|
||||
default:
|
||||
cmd.Println("Invalid type given")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unfollowDomains(cmd *cobra.Command, args []string) error {
|
||||
subscriptions := relayState.Subscriptions
|
||||
for _, domain := range args {
|
||||
if contains(subscriptions, domain) {
|
||||
subscription := *relayState.SelectSubscription(domain)
|
||||
createUnfollowRequestResponse(subscription)
|
||||
relayState.DelSubscription(subscription.Domain)
|
||||
cmd.Println("Unfollow [" + subscription.Domain + "]")
|
||||
break
|
||||
} else {
|
||||
cmd.Println("Invalid domain [" + domain + "] given")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
245
control/domain_test.go
Normal file
245
control/domain_test.go
Normal file
@ -0,0 +1,245 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListDomainSubscriber(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetOutput(buffer)
|
||||
app.SetArgs([]string{"list"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
valid := ` - Subscriber domain :
|
||||
subscription.example.jp
|
||||
Total : 1
|
||||
`
|
||||
if output != valid {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListDomainLimited(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetOutput(buffer)
|
||||
app.SetArgs([]string{"list", "-t", "limited"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
valid := ` - Limited domain :
|
||||
limitedDomain.example.jp
|
||||
Total : 1
|
||||
`
|
||||
if output != valid {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListDomainBlocked(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetOutput(buffer)
|
||||
app.SetArgs([]string{"list", "-t", "blocked"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
valid := ` - Blocked domain :
|
||||
blockedDomain.example.jp
|
||||
Total : 1
|
||||
`
|
||||
if output != valid {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDomainBlocked(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := domainCmdInit()
|
||||
|
||||
app.SetArgs([]string{"set", "-t", "blocked", "testdomain.example.jp"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
valid := false
|
||||
for _, domain := range relayState.BlockedDomains {
|
||||
if domain == "testdomain.example.jp" {
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatalf("Not set blocked domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDomainLimited(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := domainCmdInit()
|
||||
|
||||
app.SetArgs([]string{"set", "-t", "limited", "testdomain.example.jp"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
valid := false
|
||||
for _, domain := range relayState.LimitedDomains {
|
||||
if domain == "testdomain.example.jp" {
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatalf("Not set limited domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsetDomainBlocked(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetArgs([]string{"set", "-t", "blocked", "-u", "blockedDomain.example.jp"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
valid := true
|
||||
for _, domain := range relayState.BlockedDomains {
|
||||
if domain == "blockedDomain.example.jp" {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatalf("Not unset blocked domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnsetDomainLimited(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetArgs([]string{"set", "-t", "limited", "-u", "limitedDomain.example.jp"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
valid := true
|
||||
for _, domain := range relayState.LimitedDomains {
|
||||
if domain == "limitedDomain.example.jp" {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatalf("Not unset blocked domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDomainInvalid(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetOutput(buffer)
|
||||
app.SetArgs([]string{"set", "-t", "hoge", "hoge.example.jp"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != "Invalid type given" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnfollowDomain(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetArgs([]string{"unfollow", "subscription.example.jp"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
valid := true
|
||||
for _, domain := range relayState.Subscriptions {
|
||||
if domain.Domain == "subscription.example.jp" {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatalf("Not unfollowed domain")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidUnfollowDomain(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
relayState.Load()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
app = domainCmdInit()
|
||||
app.SetOutput(buffer)
|
||||
app.SetArgs([]string{"unfollow", "unknown.tld"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != "Invalid domain [unknown.tld] given" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
215
control/follow.go
Normal file
215
control/follow.go
Normal file
@ -0,0 +1,215 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/RichardKnop/machinery/v1/tasks"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yukimochi/Activity-Relay/models"
|
||||
)
|
||||
|
||||
func followCmdInit() *cobra.Command {
|
||||
var follow = &cobra.Command{
|
||||
Use: "follow",
|
||||
Short: "Manage follow request for relay",
|
||||
Long: "List all follow request and accept/reject follow requests.",
|
||||
}
|
||||
|
||||
var followList = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List follow request",
|
||||
Long: "List follow request.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initProxyE(listFollows, cmd, args)
|
||||
},
|
||||
}
|
||||
follow.AddCommand(followList)
|
||||
|
||||
var followAccept = &cobra.Command{
|
||||
Use: "accept",
|
||||
Short: "Accept follow request",
|
||||
Long: "Accept follow request by domain.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initProxyE(acceptFollow, cmd, args)
|
||||
},
|
||||
}
|
||||
follow.AddCommand(followAccept)
|
||||
|
||||
var followReject = &cobra.Command{
|
||||
Use: "reject",
|
||||
Short: "Reject follow request",
|
||||
Long: "Reject follow request by domain.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initProxyE(rejectFollow, cmd, args)
|
||||
},
|
||||
}
|
||||
follow.AddCommand(followReject)
|
||||
|
||||
var updateActor = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update actor object",
|
||||
Long: "Update actor object for whole subscribers.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initProxyE(updateActor, cmd, args)
|
||||
},
|
||||
}
|
||||
follow.AddCommand(updateActor)
|
||||
|
||||
return follow
|
||||
}
|
||||
|
||||
func pushRegistorJob(inboxURL string, body []byte) {
|
||||
job := &tasks.Signature{
|
||||
Name: "registor",
|
||||
RetryCount: 25,
|
||||
Args: []tasks.Arg{
|
||||
{
|
||||
Name: "inboxURL",
|
||||
Type: "string",
|
||||
Value: inboxURL,
|
||||
},
|
||||
{
|
||||
Name: "body",
|
||||
Type: "string",
|
||||
Value: string(body),
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := machineryServer.SendTask(job)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
||||
func createFollowRequestResponse(domain string, response string) error {
|
||||
data, err := relayState.RedisClient.HGetAll("relay:pending:" + domain).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
activity := models.Activity{
|
||||
Context: []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"},
|
||||
ID: data["activity_id"],
|
||||
Actor: data["actor"],
|
||||
Type: data["type"],
|
||||
Object: data["object"],
|
||||
}
|
||||
|
||||
resp := activity.GenerateResponse(globalConfig.ServerHostname(), response)
|
||||
jsonData, err := json.Marshal(&resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pushRegistorJob(data["inbox_url"], jsonData)
|
||||
relayState.RedisClient.Del("relay:pending:" + domain)
|
||||
if response == "Accept" {
|
||||
relayState.AddSubscription(models.Subscription{
|
||||
Domain: domain,
|
||||
InboxURL: data["inbox_url"],
|
||||
ActivityID: data["activity_id"],
|
||||
ActorID: data["actor"],
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createUpdateActorActivity(subscription models.Subscription) error {
|
||||
activity := models.Activity{
|
||||
Context: []string{"https://www.w3.org/ns/activitystreams"},
|
||||
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,
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(&activity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pushRegistorJob(subscription.InboxURL, jsonData)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listFollows(cmd *cobra.Command, args []string) error {
|
||||
var domains []string
|
||||
cmd.Println(" - Follow request :")
|
||||
follows, err := relayState.RedisClient.Keys("relay:pending:*").Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, follow := range follows {
|
||||
domains = append(domains, strings.Replace(follow, "relay:pending:", "", 1))
|
||||
}
|
||||
for _, domain := range domains {
|
||||
cmd.Println(domain)
|
||||
}
|
||||
cmd.Println(fmt.Sprintf("Total : %d", len(domains)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func acceptFollow(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
var domains []string
|
||||
follows, err := relayState.RedisClient.Keys("relay:pending:*").Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, follow := range follows {
|
||||
domains = append(domains, strings.Replace(follow, "relay:pending:", "", 1))
|
||||
}
|
||||
|
||||
for _, domain := range args {
|
||||
if contains(domains, domain) {
|
||||
cmd.Println("Accept [" + domain + "] follow request")
|
||||
createFollowRequestResponse(domain, "Accept")
|
||||
} else {
|
||||
cmd.Println("Invalid domain [" + domain + "] given")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func rejectFollow(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
var domains []string
|
||||
follows, err := relayState.RedisClient.Keys("relay:pending:*").Result()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, follow := range follows {
|
||||
domains = append(domains, strings.Replace(follow, "relay:pending:", "", 1))
|
||||
}
|
||||
|
||||
for _, domain := range args {
|
||||
for _, request := range domains {
|
||||
if domain == request {
|
||||
cmd.Println("Reject [" + domain + "] follow request")
|
||||
createFollowRequestResponse(domain, "Reject")
|
||||
break
|
||||
}
|
||||
}
|
||||
cmd.Println("Invalid domain [" + domain + "] given")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateActor(cmd *cobra.Command, args []string) error {
|
||||
for _, subscription := range relayState.Subscriptions {
|
||||
err := createUpdateActorActivity(subscription)
|
||||
if err != nil {
|
||||
cmd.Println("Failed Update Actor for " + subscription.Domain)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
136
control/follow_test.go
Normal file
136
control/follow_test.go
Normal file
@ -0,0 +1,136 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListFollows(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := followCmdInit()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
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://" + globalConfig.ServerHostname().Host + "/actor",
|
||||
})
|
||||
|
||||
app.SetArgs([]string{"list"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
valid := ` - Follow request :
|
||||
example.com
|
||||
Total : 1
|
||||
`
|
||||
if output != valid {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptFollow(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
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://" + globalConfig.ServerHostname().Host + "/actor",
|
||||
})
|
||||
|
||||
app.SetArgs([]string{"accept", "example.com"})
|
||||
app.Execute()
|
||||
|
||||
valid, _ := relayState.RedisClient.Exists("relay:pending:example.com").Result()
|
||||
if valid != 0 {
|
||||
t.Fatalf("Not removed follow request.")
|
||||
}
|
||||
|
||||
valid, _ = relayState.RedisClient.Exists("relay:subscription:example.com").Result()
|
||||
if valid != 1 {
|
||||
t.Fatalf("Not created subscription.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectFollow(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
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://" + globalConfig.ServerHostname().Host + "/actor",
|
||||
})
|
||||
|
||||
app.SetArgs([]string{"reject", "example.com"})
|
||||
app.Execute()
|
||||
|
||||
valid, _ := relayState.RedisClient.Exists("relay:pending:example.com").Result()
|
||||
if valid != 0 {
|
||||
t.Fatalf("No response follow request.")
|
||||
}
|
||||
|
||||
valid, _ = relayState.RedisClient.Exists("relay:subscription:example.com").Result()
|
||||
if valid != 0 {
|
||||
t.Fatalf("Created subscription.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidFollow(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := followCmdInit()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"accept", "unknown.tld"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != "Invalid domain [unknown.tld] given" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidRejectFollow(t *testing.T) {
|
||||
relayState.RedisClient.FlushAll().Result()
|
||||
|
||||
app := followCmdInit()
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
app.SetOutput(buffer)
|
||||
|
||||
app.SetArgs([]string{"reject", "unknown.tld"})
|
||||
app.Execute()
|
||||
|
||||
output := buffer.String()
|
||||
if strings.Split(output, "\n")[0] != "Invalid domain [unknown.tld] given" {
|
||||
t.Fatalf("Invalid Response.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUpdateActorActivity(t *testing.T) {
|
||||
app := configCmdInit()
|
||||
|
||||
app.SetArgs([]string{"import", "--json", "../misc/exampleConfig.json"})
|
||||
app.Execute()
|
||||
|
||||
app = followCmdInit()
|
||||
|
||||
app.SetArgs([]string{"update"})
|
||||
app.Execute()
|
||||
}
|
24
control/utils.go
Normal file
24
control/utils.go
Normal file
@ -0,0 +1,24 @@
|
||||
package control
|
||||
|
||||
import "github.com/yukimochi/Activity-Relay/models"
|
||||
|
||||
func contains(entries interface{}, finder string) bool {
|
||||
switch entry := entries.(type) {
|
||||
case string:
|
||||
return entry == finder
|
||||
case []string:
|
||||
for i := 0; i < len(entry); i++ {
|
||||
if entry[i] == finder {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case []models.Subscription:
|
||||
for i := 0; i < len(entry); i++ {
|
||||
if entry[i].Domain == finder {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
32
control/utils_test.go
Normal file
32
control/utils_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package control
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
data := "nil"
|
||||
sData := []string{
|
||||
"no",
|
||||
"nil",
|
||||
}
|
||||
badData := 0
|
||||
result := contains(data, "true")
|
||||
if result != false {
|
||||
t.Fatalf("Failed - no contain but true.")
|
||||
}
|
||||
result = contains(data, "nil")
|
||||
if result != true {
|
||||
t.Fatalf("Failed - contain but false.")
|
||||
}
|
||||
result = contains(sData, "true")
|
||||
if result != false {
|
||||
t.Fatalf("Failed - no contain but true. (slice)")
|
||||
}
|
||||
result = contains(sData, "nil")
|
||||
if result != true {
|
||||
t.Fatalf("Failed - contain but false. (slice)")
|
||||
}
|
||||
result = contains(badData, "hoge")
|
||||
if result != false {
|
||||
t.Fatalf("Failed - input bad data but true. (slice)")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user