Fix styles.

This commit is contained in:
Naoki Kosaka 2018-12-09 20:40:17 +09:00
parent edafcf140f
commit 6ce65295bb
15 changed files with 233 additions and 220 deletions

View File

@ -15,33 +15,34 @@ import (
"github.com/yukimochi/httpsig"
)
var UA_STRING = os.Getenv("RELAY_SERVICENAME") + " (golang net/http; Activity-Relay v0.1.1; " + os.Getenv("RELAY_DOMAIN") + ")"
// UaString : Use for User-Agent
var UaString = os.Getenv("RELAY_SERVICENAME") + " (golang net/http; Activity-Relay v0.1.1; " + os.Getenv("RELAY_DOMAIN") + ")"
func appendSignature(r *http.Request, body *[]byte, KeyID string, pKey *rsa.PrivateKey) error {
func appendSignature(request *http.Request, body *[]byte, KeyID string, publicKey *rsa.PrivateKey) error {
hash := sha256.New()
hash.Write(*body)
b := hash.Sum(nil)
r.Header.Set("Digest", "SHA-256="+base64.StdEncoding.EncodeToString(b))
r.Header.Set("Host", r.Host)
request.Header.Set("Digest", "SHA-256="+base64.StdEncoding.EncodeToString(b))
request.Header.Set("Host", request.Host)
signer, _, err := httpsig.NewSigner([]httpsig.Algorithm{httpsig.RSA_SHA256}, []string{httpsig.RequestTarget, "Host", "Date", "Digest", "Content-Type"}, httpsig.Signature)
if err != nil {
return err
}
err = signer.SignRequest(pKey, KeyID, r)
err = signer.SignRequest(publicKey, KeyID, request)
if err != nil {
return err
}
return nil
}
// SendActivity : Send ActivityPub Activity.
func SendActivity(inboxURL string, KeyID string, refBytes []byte, pKey *rsa.PrivateKey) error {
req, _ := http.NewRequest("POST", inboxURL, bytes.NewBuffer(refBytes))
// SendActivity : Send ActivityPub activity
func SendActivity(inboxURL string, KeyID string, body []byte, publicKey *rsa.PrivateKey) error {
req, _ := http.NewRequest("POST", inboxURL, bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/activity+json, application/ld+json")
req.Header.Set("User-Agent", UA_STRING)
req.Header.Set("User-Agent", UaString)
req.Header.Set("Date", httpdate.Time2Str(time.Now()))
appendSignature(req, &refBytes, KeyID, pKey)
appendSignature(req, &body, KeyID, publicKey)
client := &http.Client{Timeout: time.Duration(5) * time.Second}
resp, err := client.Do(req)
if err != nil {

View File

@ -35,23 +35,25 @@ type Actor struct {
PublicKey PublicKey `json:"publicKey"`
}
func (a *Actor) GenerateSelfKey(hostname *url.URL, publickey *rsa.PublicKey) {
a.Context = []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"}
a.ID = hostname.String() + "/actor"
a.Type = "Service"
a.PreferredUsername = "relay"
a.Inbox = hostname.String() + "/inbox"
a.PublicKey = PublicKey{
// GenerateSelfKey : Generate relay Actor from Publickey.
func (actor *Actor) GenerateSelfKey(hostname *url.URL, publickey *rsa.PublicKey) {
actor.Context = []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"}
actor.ID = hostname.String() + "/actor"
actor.Type = "Service"
actor.PreferredUsername = "relay"
actor.Inbox = hostname.String() + "/inbox"
actor.PublicKey = PublicKey{
hostname.String() + "/actor#main-key",
hostname.String() + "/actor",
keyloader.GeneratePublicKeyPEMString(publickey),
}
}
func (a *Actor) RetrieveRemoteActor(url string) error {
// RetrieveRemoteActor : Retrieve Actor from remote instance.
func (actor *Actor) RetrieveRemoteActor(url string) error {
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Accept", "application/activity+json, application/ld+json")
req.Header.Set("User-Agent", UA_STRING)
req.Header.Set("User-Agent", UaString)
client := new(http.Client)
resp, err := client.Do(req)
if err != nil {
@ -60,7 +62,7 @@ func (a *Actor) RetrieveRemoteActor(url string) error {
defer resp.Body.Close()
data, _ := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(data, &a)
err = json.Unmarshal(data, &actor)
if err != nil {
return err
}
@ -78,32 +80,35 @@ type Activity struct {
Cc []string `json:"cc"`
}
func (a *Activity) GenerateResponse(host *url.URL, responseType string) Activity {
// GenerateResponse : Generate activity response.
func (activity *Activity) GenerateResponse(host *url.URL, responseType string) Activity {
return Activity{
[]string{"https://www.w3.org/ns/activitystreams"},
host.String() + "/activities/" + uuid.NewV4().String(),
host.String() + "/actor",
responseType,
&a,
&activity,
nil,
nil,
}
}
func (a *Activity) GenerateAnnounce(host *url.URL) Activity {
// GenerateAnnounce : Generate Announce of activity.
func (activity *Activity) GenerateAnnounce(host *url.URL) Activity {
return Activity{
[]string{"https://www.w3.org/ns/activitystreams"},
host.String() + "/activities/" + uuid.NewV4().String(),
host.String() + "/actor",
"Announce",
a.ID,
activity.ID,
[]string{host.String() + "/actor/followers"},
nil,
}
}
func (a *Activity) NestedActivity() (*Activity, error) {
mappedObject := a.Object.(map[string]interface{})
// NestedActivity : Unwrap nested activity.
func (activity *Activity) NestedActivity() (*Activity, error) {
mappedObject := activity.Object.(map[string]interface{})
if id, ok := mappedObject["id"].(string); ok {
if nestedType, ok := mappedObject["type"].(string); ok {
actor, ok := mappedObject["actor"].(string)
@ -153,9 +158,10 @@ type WebfingerResource struct {
Links []WebfingerLink `json:"links"`
}
func (a *WebfingerResource) GenerateFromActor(hostname *url.URL, actor *Actor) {
a.Subject = "acct:" + actor.PreferredUsername + "@" + hostname.Host
a.Links = []WebfingerLink{
// GenerateFromActor : Generate Webfinger resource from Actor.
func (resource *WebfingerResource) GenerateFromActor(hostname *url.URL, actor *Actor) {
resource.Subject = "acct:" + actor.PreferredUsername + "@" + hostname.Host
resource.Links = []WebfingerLink{
WebfingerLink{
"self",
"application/activity+json",

View File

@ -34,13 +34,13 @@ func ReadPublicKeyRSAfromString(pemString string) (*rsa.PublicKey, error) {
return pub, nil
}
func GeneratePublicKeyPEMString(pub *rsa.PublicKey) string {
pubkeyBytes := x509.MarshalPKCS1PublicKey(pub)
pubkeyPem := pem.EncodeToMemory(
func GeneratePublicKeyPEMString(publicKey *rsa.PublicKey) string {
publicKeyByte := x509.MarshalPKCS1PublicKey(publicKey)
publicKeyPem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubkeyBytes,
Bytes: publicKeyByte,
},
)
return string(pubkeyPem)
return string(publicKeyPem)
}

View File

@ -1,4 +1,4 @@
package relayconf
package state
import (
"strings"
@ -6,23 +6,29 @@ import (
"github.com/go-redis/redis"
)
// Config : Enum for RelayConfig
type Config int
const (
// BlockService : Blocking for service-type actor
BlockService Config = iota
// ManuallyAccept : Manually accept follow-request
ManuallyAccept
// CreateAsAnnounce : Announce activity instead of relay create activity
CreateAsAnnounce
)
func NewConfig(r *redis.Client) ExportConfig {
var config ExportConfig
config.RedisClient = r
// NewState : Create new RelayState instance with redis client
func NewState(redisClient *redis.Client) RelayState {
var config RelayState
config.RedisClient = redisClient
config.Load()
return config
}
type ExportConfig struct {
// RelayState : Store subscriptions and relay configrations
type RelayState struct {
RedisClient *redis.Client
RelayConfig relayConfig `json:"relayConfig"`
@ -31,7 +37,8 @@ type ExportConfig struct {
Subscriptions []Subscription `json:"subscriptions"`
}
func (config *ExportConfig) Load() {
// Load : Refrash content from redis
func (config *RelayState) Load() {
config.RelayConfig.load(config.RedisClient)
var limitedDomains []string
var blockedDomains []string
@ -63,7 +70,8 @@ func (config *ExportConfig) Load() {
config.Subscriptions = subscriptions
}
func (config *ExportConfig) SetConfig(key Config, value bool) {
// SetConfig : Set relay configration
func (config *RelayState) SetConfig(key Config, value bool) {
strValue := 0
if value {
strValue = 1
@ -79,7 +87,8 @@ func (config *ExportConfig) SetConfig(key Config, value bool) {
config.Load()
}
func (config *ExportConfig) AddSubscription(domain Subscription) {
// AddSubscription : Add new instance for subscription list
func (config *RelayState) AddSubscription(domain Subscription) {
config.RedisClient.HMSet("relay:subscription:"+domain.Domain, map[string]interface{}{
"inbox_url": domain.InboxURL,
"activity_id": domain.ActivityID,
@ -89,14 +98,16 @@ func (config *ExportConfig) AddSubscription(domain Subscription) {
config.Load()
}
func (config *ExportConfig) DelSubscription(domain string) {
// DelSubscription : Delete instance from subscription list
func (config *RelayState) DelSubscription(domain string) {
config.RedisClient.Del("relay:subscription:" + domain).Result()
config.RedisClient.Del("relay:pending:" + domain).Result()
config.Load()
}
func (config *ExportConfig) SetBlockedDomain(domain string, value bool) {
// SetBlockedDomain : Set/Unset instance for blocked domain
func (config *RelayState) SetBlockedDomain(domain string, value bool) {
if value {
config.RedisClient.HSet("relay:config:blockedDomain", domain, "1").Result()
} else {
@ -106,7 +117,8 @@ func (config *ExportConfig) SetBlockedDomain(domain string, value bool) {
config.Load()
}
func (config *ExportConfig) SetLimitedDomain(domain string, value bool) {
// SetLimitedDomain : Set/Unset instance for limited domain
func (config *RelayState) SetLimitedDomain(domain string, value bool) {
if value {
config.RedisClient.HSet("relay:config:limitedDomain", domain, "1").Result()
} else {
@ -116,6 +128,7 @@ func (config *ExportConfig) SetLimitedDomain(domain string, value bool) {
config.Load()
}
// Subscription : Instance subscription information
type Subscription struct {
Domain string `json:"domain"`
InboxURL string `json:"inbox_url"`
@ -123,23 +136,22 @@ type Subscription struct {
ActorID string `json:"actor_id"`
}
// RelayConfig : struct for relay configuration
type relayConfig struct {
BlockService bool `json:"blockService"`
ManuallyAccept bool `json:"manuallyAccept"`
CreateAsAnnounce bool `json:"createAsAnnounce"`
}
func (config *relayConfig) load(r *redis.Client) {
blockService, err := r.HGet("relay:config", "block_service").Result()
func (config *relayConfig) load(redisClient *redis.Client) {
blockService, err := redisClient.HGet("relay:config", "block_service").Result()
if err != nil {
blockService = "0"
}
manuallyAccept, err := r.HGet("relay:config", "manually_accept").Result()
manuallyAccept, err := redisClient.HGet("relay:config", "manually_accept").Result()
if err != nil {
manuallyAccept = "0"
}
createAsAnnounce, err := r.HGet("relay:config", "create_as_announce").Result()
createAsAnnounce, err := redisClient.HGet("relay:config", "create_as_announce").Result()
if err != nil {
createAsAnnounce = "0"
}

View File

@ -7,19 +7,19 @@ import (
"net/url"
"os"
machinery "github.com/RichardKnop/machinery/v1"
"github.com/RichardKnop/machinery/v1"
"github.com/RichardKnop/machinery/v1/config"
"github.com/go-redis/redis"
"github.com/urfave/cli"
"github.com/yukimochi/Activity-Relay/KeyLoader"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
var hostname *url.URL
var hostkey *rsa.PrivateKey
var redClient *redis.Client
var macServer *machinery.Server
var exportConfig relayconf.ExportConfig
var relayState state.RelayState
func main() {
pemPath := os.Getenv("ACTOR_PEM")
@ -140,7 +140,7 @@ func main() {
},
{
Name: "manually-accept",
Usage: "Enable Manually accept follow-request",
Usage: "Enable manually accept follow-request",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "undo, u",
@ -151,7 +151,7 @@ func main() {
},
{
Name: "create-as-announce",
Usage: "Enable Announce activity instead of relay create activity (Not recommended)",
Usage: "Enable announce activity instead of relay create activity (Not recommend)",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "undo, u",
@ -197,7 +197,7 @@ func main() {
},
}
exportConfig = relayconf.NewConfig(redClient)
relayState = state.NewState(redClient)
err = app.Run(os.Args)
if err != nil {
log.Fatal(err)

View File

@ -9,7 +9,7 @@ import (
"github.com/RichardKnop/machinery/v1/config"
"github.com/go-redis/redis"
"github.com/yukimochi/Activity-Relay/KeyLoader"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
func TestMain(m *testing.M) {
@ -31,7 +31,7 @@ func TestMain(m *testing.M) {
}
macServer, _ = machinery.NewServer(macConfig)
redClient.FlushAll().Result()
exportConfig = relayconf.NewConfig(redClient)
relayState = state.NewState(redClient)
code := m.Run()
os.Exit(code)
redClient.FlushAll().Result()

View File

@ -7,53 +7,53 @@ import (
"os"
"github.com/urfave/cli"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
const (
BlockService relayconf.Config = iota
BlockService state.Config = iota
ManuallyAccept
CreateAsAnnounce
)
func serviceBlock(c *cli.Context) {
if c.Bool("undo") {
exportConfig.SetConfig(BlockService, false)
relayState.SetConfig(BlockService, false)
fmt.Println("Blocking for service-type actor is Disabled.")
} else {
exportConfig.SetConfig(BlockService, true)
relayState.SetConfig(BlockService, true)
fmt.Println("Blocking for service-type actor is Enabled.")
}
}
func manuallyAccept(c *cli.Context) {
if c.Bool("undo") {
exportConfig.SetConfig(ManuallyAccept, false)
relayState.SetConfig(ManuallyAccept, false)
fmt.Println("Manually accept follow-request is Disabled.")
} else {
exportConfig.SetConfig(ManuallyAccept, true)
relayState.SetConfig(ManuallyAccept, true)
fmt.Println("Manually accept follow-request is Enabled.")
}
}
func createAsAnnounce(c *cli.Context) {
if c.Bool("undo") {
exportConfig.SetConfig(CreateAsAnnounce, false)
relayState.SetConfig(CreateAsAnnounce, false)
fmt.Println("Announce activity instead of relay create activity is Disabled.")
} else {
exportConfig.SetConfig(CreateAsAnnounce, true)
relayState.SetConfig(CreateAsAnnounce, true)
fmt.Println("Announce activity instead of relay create activity is Enabled.")
}
}
func listConfigs(c *cli.Context) {
fmt.Println("Blocking for service-type actor : ", exportConfig.RelayConfig.BlockService)
fmt.Println("Manually accept follow-request : ", exportConfig.RelayConfig.ManuallyAccept)
fmt.Println("Announce activity instead of relay create activity : ", exportConfig.RelayConfig.CreateAsAnnounce)
fmt.Println("Blocking for service-type actor : ", relayState.RelayConfig.BlockService)
fmt.Println("Manually accept follow-request : ", relayState.RelayConfig.ManuallyAccept)
fmt.Println("Announce activity instead of relay create activity : ", relayState.RelayConfig.CreateAsAnnounce)
}
func exportConfigs(c *cli.Context) {
jsonData, _ := json.Marshal(&exportConfig)
jsonData, _ := json.Marshal(&relayState)
fmt.Println(string(jsonData))
}
@ -68,7 +68,7 @@ func importConfigs(c *cli.Context) {
fmt.Fprintln(os.Stderr, err)
return
}
var data relayconf.ExportConfig
var data state.RelayState
err = json.Unmarshal(jsonData, &data)
if err != nil {
fmt.Fprintln(os.Stderr, err)
@ -76,24 +76,24 @@ func importConfigs(c *cli.Context) {
}
if data.RelayConfig.BlockService {
exportConfig.SetConfig(BlockService, true)
relayState.SetConfig(BlockService, true)
}
if data.RelayConfig.ManuallyAccept {
exportConfig.SetConfig(ManuallyAccept, true)
relayState.SetConfig(ManuallyAccept, true)
}
if data.RelayConfig.CreateAsAnnounce {
exportConfig.SetConfig(CreateAsAnnounce, true)
relayState.SetConfig(CreateAsAnnounce, true)
}
for _, LimitedDomain := range data.LimitedDomains {
exportConfig.SetLimitedDomain(LimitedDomain, true)
relayState.SetLimitedDomain(LimitedDomain, true)
redClient.HSet("relay:config:limitedDomain", LimitedDomain, "1")
}
for _, BlockedDomain := range data.BlockedDomains {
exportConfig.SetLimitedDomain(BlockedDomain, true)
relayState.SetLimitedDomain(BlockedDomain, true)
redClient.HSet("relay:config:blockedDomain", BlockedDomain, "1")
}
for _, Subscription := range data.Subscriptions {
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: Subscription.Domain,
InboxURL: Subscription.InboxURL,
ActivityID: Subscription.ActivityID,

View File

@ -25,14 +25,14 @@ func TestServiceBlock(t *testing.T) {
fooCmd,
}
exportConfig.SetConfig(BlockService, false)
relayState.SetConfig(BlockService, false)
app.Run([]string{"", "service-block"})
if !exportConfig.RelayConfig.BlockService {
if !relayState.RelayConfig.BlockService {
t.Fatalf("Not Enabled ServiceBlock feature,")
}
app.Run([]string{"", "service-block", "-u"})
if exportConfig.RelayConfig.BlockService {
if relayState.RelayConfig.BlockService {
t.Fatalf("Not Disabled ServiceBlock feature,")
}
}
@ -54,14 +54,14 @@ func TestManuallyAccept(t *testing.T) {
fooCmd,
}
exportConfig.SetConfig(ManuallyAccept, false)
relayState.SetConfig(ManuallyAccept, false)
app.Run([]string{"", "manually-accept"})
if !exportConfig.RelayConfig.ManuallyAccept {
if !relayState.RelayConfig.ManuallyAccept {
t.Fatalf("Not Enabled Manually accept follow-request feature,")
}
app.Run([]string{"", "manually-accept", "-u"})
if exportConfig.RelayConfig.ManuallyAccept {
if relayState.RelayConfig.ManuallyAccept {
t.Fatalf("Not Disabled Manually accept follow-request feature,")
}
}
@ -83,14 +83,14 @@ func TestCreateAsAnnounce(t *testing.T) {
fooCmd,
}
exportConfig.SetConfig(CreateAsAnnounce, false)
relayState.SetConfig(CreateAsAnnounce, false)
app.Run([]string{"", "create-as-announce"})
if !exportConfig.RelayConfig.CreateAsAnnounce {
if !relayState.RelayConfig.CreateAsAnnounce {
t.Fatalf("Not Enabled Announce activity instead of relay create activity feature,")
}
app.Run([]string{"", "create-as-announce", "-u"})
if exportConfig.RelayConfig.CreateAsAnnounce {
if relayState.RelayConfig.CreateAsAnnounce {
t.Fatalf("Not Disabled Announce activity instead of relay create activity feature,")
}
}
@ -106,9 +106,9 @@ func TestListConfigs(t *testing.T) {
fooCmd,
}
exportConfig.SetConfig(BlockService, true)
exportConfig.SetConfig(ManuallyAccept, true)
exportConfig.SetConfig(CreateAsAnnounce, true)
relayState.SetConfig(BlockService, true)
relayState.SetConfig(ManuallyAccept, true)
relayState.SetConfig(CreateAsAnnounce, true)
out := capturer.CaptureStdout(func() {
app.Run([]string{"", "show"})
})
@ -130,9 +130,9 @@ func TestListConfigs(t *testing.T) {
}
}
exportConfig.SetConfig(BlockService, false)
exportConfig.SetConfig(ManuallyAccept, false)
exportConfig.SetConfig(CreateAsAnnounce, false)
relayState.SetConfig(BlockService, false)
relayState.SetConfig(ManuallyAccept, false)
relayState.SetConfig(CreateAsAnnounce, false)
out = capturer.CaptureStdout(func() {
app.Run([]string{"", "show"})
})

View File

@ -11,13 +11,13 @@ func listDomains(c *cli.Context) error {
switch c.String("type") {
case "limited":
fmt.Println(" - Limited domain :")
domains = exportConfig.LimitedDomains
domains = relayState.LimitedDomains
case "blocked":
fmt.Println(" - Blocked domain :")
domains = exportConfig.BlockedDomains
domains = relayState.BlockedDomains
default:
fmt.Println(" - Subscribed domain :")
temp := exportConfig.Subscriptions
temp := relayState.Subscriptions
for _, domain := range temp {
domains = append(domains, domain.Domain)
}
@ -37,18 +37,18 @@ func setDomainType(c *cli.Context) error {
switch c.String("type") {
case "limited":
if c.Bool("undo") {
exportConfig.SetLimitedDomain(c.String("domain"), false)
relayState.SetLimitedDomain(c.String("domain"), false)
fmt.Println("Unset [" + c.String("domain") + "] as Limited domain.")
} else {
exportConfig.SetLimitedDomain(c.String("domain"), true)
relayState.SetLimitedDomain(c.String("domain"), true)
fmt.Println("Set [" + c.String("domain") + "] as Limited domain.")
}
case "blocked":
if c.Bool("undo") {
exportConfig.SetBlockedDomain(c.String("domain"), false)
relayState.SetBlockedDomain(c.String("domain"), false)
fmt.Println("Unset [" + c.String("domain") + "] as Blocked domain.")
} else {
exportConfig.SetBlockedDomain(c.String("domain"), true)
relayState.SetBlockedDomain(c.String("domain"), true)
fmt.Println("Set [" + c.String("domain") + "] as Blocked domain.")
}
default:

View File

@ -70,13 +70,11 @@ func acceptFollow(c *cli.Context) error {
return err
}
activity := activitypub.Activity{
[]string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"},
data["activity_id"],
data["actor"],
data["type"],
data["object"],
nil,
nil,
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(hostname, "Accept")
@ -85,11 +83,10 @@ func acceptFollow(c *cli.Context) error {
pushRegistorJob(data["inbox_url"], jsonData)
redClient.HSet("relay:subscription:"+domain, "inbox_url", data["inbox_url"])
redClient.Del("relay:pending:" + domain)
return nil
} else {
fmt.Println("No domain given.")
return nil
}
return nil
}
func rejectFollow(c *cli.Context) error {
@ -110,13 +107,11 @@ func rejectFollow(c *cli.Context) error {
return err
}
activity := activitypub.Activity{
[]string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"},
data["activity_id"],
data["actor"],
data["type"],
data["object"],
nil,
nil,
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(hostname, "Reject")
@ -124,9 +119,8 @@ func rejectFollow(c *cli.Context) error {
pushRegistorJob(data["inbox_url"], jsonData)
redClient.Del("relay:pending:" + domain)
return nil
} else {
fmt.Println("No domain given.")
return nil
}
return nil
}

View File

@ -13,14 +13,14 @@ import (
"github.com/yukimochi/httpsig"
)
func decodeActivity(r *http.Request) (*activitypub.Activity, *activitypub.Actor, []byte, error) {
r.Header.Set("Host", r.Host)
dataLen, _ := strconv.Atoi(r.Header.Get("Content-Length"))
func decodeActivity(request *http.Request) (*activitypub.Activity, *activitypub.Actor, []byte, error) {
request.Header.Set("Host", request.Host)
dataLen, _ := strconv.Atoi(request.Header.Get("Content-Length"))
body := make([]byte, dataLen)
r.Body.Read(body)
request.Body.Read(body)
// Verify HTTPSignature
verifier, err := httpsig.NewVerifier(r)
verifier, err := httpsig.NewVerifier(request)
if err != nil {
return nil, nil, nil, err
}
@ -40,7 +40,7 @@ func decodeActivity(r *http.Request) (*activitypub.Activity, *activitypub.Actor,
}
// Verify Digest
givenDigest := r.Header.Get("Digest")
givenDigest := request.Header.Get("Digest")
hash := sha256.New()
hash.Write(body)
b := hash.Sum(nil)

102
handle.go
View File

@ -10,14 +10,14 @@ import (
"github.com/RichardKnop/machinery/v1/tasks"
"github.com/yukimochi/Activity-Relay/ActivityPub"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
func handleWebfinger(w http.ResponseWriter, r *http.Request) {
resource := r.URL.Query()["resource"]
if r.Method != "GET" || len(resource) == 0 {
w.WriteHeader(400)
w.Write(nil)
func handleWebfinger(writer http.ResponseWriter, request *http.Request) {
resource := request.URL.Query()["resource"]
if request.Method != "GET" || len(resource) == 0 {
writer.WriteHeader(400)
writer.Write(nil)
} else {
request := resource[0]
if request == WebfingerResource.Subject {
@ -25,28 +25,28 @@ func handleWebfinger(w http.ResponseWriter, r *http.Request) {
if err != nil {
panic(err)
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(200)
w.Write(wfresource)
writer.Header().Add("Content-Type", "application/json")
writer.WriteHeader(200)
writer.Write(wfresource)
} else {
w.WriteHeader(404)
w.Write(nil)
writer.WriteHeader(404)
writer.Write(nil)
}
}
}
func handleActor(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
func handleActor(writer http.ResponseWriter, request *http.Request) {
if request.Method == "GET" {
actor, err := json.Marshal(&Actor)
if err != nil {
panic(err)
}
w.Header().Add("Content-Type", "application/activity+json")
w.WriteHeader(200)
w.Write(actor)
writer.Header().Add("Content-Type", "application/activity+json")
writer.WriteHeader(200)
writer.Write(actor)
} else {
w.WriteHeader(400)
w.Write(nil)
writer.WriteHeader(400)
writer.Write(nil)
}
}
@ -61,7 +61,7 @@ func contains(entries interface{}, finder string) bool {
}
}
return false
case []relayconf.Subscription:
case []state.Subscription:
for i := 0; i < len(entry); i++ {
if entry[i].Domain == finder {
return true
@ -73,7 +73,7 @@ func contains(entries interface{}, finder string) bool {
}
func pushRelayJob(sourceInbox string, body []byte) {
for _, domain := range exportConfig.Subscriptions {
for _, domain := range relayState.Subscriptions {
if sourceInbox != domain.Domain {
job := &tasks.Signature{
Name: "relay",
@ -140,7 +140,7 @@ func unFollowAcceptable(activity *activitypub.Activity, actor *activitypub.Actor
func suitableFollow(activity *activitypub.Activity, actor *activitypub.Actor) bool {
domain, _ := url.Parse(activity.Actor)
if contains(exportConfig.BlockedDomains, domain.Host) {
if contains(relayState.BlockedDomains, domain.Host) {
return false
}
return true
@ -151,7 +151,7 @@ func relayAcceptable(activity *activitypub.Activity, actor *activitypub.Actor) e
return errors.New("Activity should contain https://www.w3.org/ns/activitystreams#Public as receiver")
}
domain, _ := url.Parse(activity.Actor)
if contains(exportConfig.Subscriptions, domain.Host) {
if contains(relayState.Subscriptions, domain.Host) {
return nil
}
return errors.New("To use the relay service, Subscribe me in advance")
@ -159,24 +159,24 @@ func relayAcceptable(activity *activitypub.Activity, actor *activitypub.Actor) e
func suitableRelay(activity *activitypub.Activity, actor *activitypub.Actor) bool {
domain, _ := url.Parse(activity.Actor)
if contains(exportConfig.LimitedDomains, domain.Host) {
if contains(relayState.LimitedDomains, domain.Host) {
return false
}
if exportConfig.RelayConfig.BlockService && actor.Type == "Service" {
if relayState.RelayConfig.BlockService && actor.Type == "Service" {
return false
}
return true
}
func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*http.Request) (*activitypub.Activity, *activitypub.Actor, []byte, error)) {
switch r.Method {
func handleInbox(writer http.ResponseWriter, request *http.Request, activityDecoder func(*http.Request) (*activitypub.Activity, *activitypub.Actor, []byte, error)) {
switch request.Method {
case "POST":
activity, actor, body, err := activityDecoder(r)
activity, actor, body, err := activityDecoder(request)
if err != nil {
w.WriteHeader(400)
w.Write(nil)
writer.WriteHeader(400)
writer.Write(nil)
} else {
exportConfig.Load()
relayState.Load()
domain, _ := url.Parse(activity.Actor)
switch activity.Type {
case "Follow":
@ -187,11 +187,11 @@ func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*h
go pushRegistorJob(actor.Inbox, jsonData)
fmt.Println("Reject Follow Request : ", err.Error(), activity.Actor)
w.WriteHeader(202)
w.Write(nil)
writer.WriteHeader(202)
writer.Write(nil)
} else {
if suitableFollow(activity, actor) {
if exportConfig.RelayConfig.ManuallyAccept {
if relayState.RelayConfig.ManuallyAccept {
redClient.HMSet("relay:pending:"+domain.Host, map[string]interface{}{
"inbox_url": actor.Endpoints.SharedInbox,
"activity_id": activity.ID,
@ -204,7 +204,7 @@ func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*h
resp := activity.GenerateResponse(hostname, "Accept")
jsonData, _ := json.Marshal(&resp)
go pushRegistorJob(actor.Inbox, jsonData)
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: actor.Endpoints.SharedInbox,
ActivityID: activity.ID,
@ -219,8 +219,8 @@ func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*h
fmt.Println("Reject Follow Request : ", activity.Actor)
}
w.WriteHeader(202)
w.Write(nil)
writer.WriteHeader(202)
writer.Write(nil)
}
case "Undo":
nestedActivity, _ := activity.NestedActivity()
@ -228,37 +228,37 @@ func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*h
err = unFollowAcceptable(nestedActivity, actor)
if err != nil {
fmt.Println("Reject Unfollow Request : ", err.Error())
w.WriteHeader(400)
w.Write([]byte(err.Error()))
writer.WriteHeader(400)
writer.Write([]byte(err.Error()))
} else {
redClient.Del("relay:subscription:" + domain.Host)
fmt.Println("Accept Unfollow Request : ", activity.Actor)
w.WriteHeader(202)
w.Write(nil)
writer.WriteHeader(202)
writer.Write(nil)
}
} else {
err = relayAcceptable(activity, actor)
if err != nil {
w.WriteHeader(400)
w.Write([]byte(err.Error()))
writer.WriteHeader(400)
writer.Write([]byte(err.Error()))
} else {
domain, _ := url.Parse(activity.Actor)
go pushRelayJob(domain.Host, body)
fmt.Println("Accept Relay Status : ", activity.Actor)
w.WriteHeader(202)
w.Write(nil)
writer.WriteHeader(202)
writer.Write(nil)
}
}
case "Create", "Update", "Delete", "Announce":
err = relayAcceptable(activity, actor)
if err != nil {
w.WriteHeader(400)
w.Write([]byte(err.Error()))
writer.WriteHeader(400)
writer.Write([]byte(err.Error()))
} else {
if suitableRelay(activity, actor) {
if exportConfig.RelayConfig.CreateAsAnnounce && activity.Type == "Create" {
if relayState.RelayConfig.CreateAsAnnounce && activity.Type == "Create" {
nestedObject, err := activity.NestedActivity()
if err != nil {
fmt.Println("Fail Assert activity : activity.Actor")
@ -280,13 +280,13 @@ func handleInbox(w http.ResponseWriter, r *http.Request, activityDecoder func(*h
fmt.Println("Skipping Relay Status : ", activity.Actor)
}
w.WriteHeader(202)
w.Write(nil)
writer.WriteHeader(202)
writer.Write(nil)
}
}
}
default:
w.WriteHeader(404)
w.Write(nil)
writer.WriteHeader(404)
writer.Write(nil)
}
}

View File

@ -12,11 +12,11 @@ import (
"testing"
"github.com/yukimochi/Activity-Relay/ActivityPub"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
const (
BlockService relayconf.Config = iota
BlockService state.Config = iota
ManuallyAccept
CreateAsAnnounce
)
@ -266,7 +266,7 @@ func TestSuitableRelayNoBlockService(t *testing.T) {
personActor := mockActor("Person")
serviceActor := mockActor("Service")
exportConfig.SetConfig(BlockService, false)
relayState.SetConfig(BlockService, false)
if suitableRelay(&activity, &personActor) != true {
t.Fatalf("Failed - Person status not relay")
@ -281,7 +281,7 @@ func TestSuitableRelayBlockService(t *testing.T) {
personActor := mockActor("Person")
serviceActor := mockActor("Service")
exportConfig.SetConfig(BlockService, true)
relayState.SetConfig(BlockService, true)
if suitableRelay(&activity, &personActor) != true {
t.Fatalf("Failed - Person status not relay")
@ -289,7 +289,7 @@ func TestSuitableRelayBlockService(t *testing.T) {
if suitableRelay(&activity, &serviceActor) != false {
t.Fatalf("Failed - Service status may relay when blocking mode")
}
exportConfig.SetConfig(BlockService, false)
relayState.SetConfig(BlockService, false)
}
func TestHandleInboxNoSignature(t *testing.T) {
@ -348,7 +348,7 @@ func TestHandleInboxValidFollow(t *testing.T) {
if res != 1 {
t.Fatalf("Failed - Subscription not works.")
}
exportConfig.DelSubscription(domain.Host)
relayState.DelSubscription(domain.Host)
}
func TestHandleInboxValidManuallyFollow(t *testing.T) {
@ -361,7 +361,7 @@ func TestHandleInboxValidManuallyFollow(t *testing.T) {
defer s.Close()
// Switch Manually
exportConfig.SetConfig(ManuallyAccept, true)
relayState.SetConfig(ManuallyAccept, true)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -380,8 +380,8 @@ func TestHandleInboxValidManuallyFollow(t *testing.T) {
if res != 0 {
t.Fatalf("Failed - Pending was skipped.")
}
exportConfig.DelSubscription(domain.Host)
exportConfig.SetConfig(ManuallyAccept, false)
relayState.DelSubscription(domain.Host)
relayState.SetConfig(ManuallyAccept, false)
}
func TestHandleInboxInvalidFollow(t *testing.T) {
@ -393,7 +393,7 @@ func TestHandleInboxInvalidFollow(t *testing.T) {
}))
defer s.Close()
exportConfig.SetConfig(ManuallyAccept, false)
relayState.SetConfig(ManuallyAccept, false)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -419,7 +419,7 @@ func TestHandleInboxValidFollowBlocked(t *testing.T) {
}))
defer s.Close()
exportConfig.SetBlockedDomain(domain.Host, true)
relayState.SetBlockedDomain(domain.Host, true)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -434,8 +434,8 @@ func TestHandleInboxValidFollowBlocked(t *testing.T) {
if res != 0 {
t.Fatalf("Failed - Subscription not blocked.")
}
exportConfig.DelSubscription(domain.Host)
exportConfig.SetBlockedDomain(domain.Host, false)
relayState.DelSubscription(domain.Host)
relayState.SetBlockedDomain(domain.Host, false)
}
func TestHandleInboxValidUnfollow(t *testing.T) {
@ -447,7 +447,7 @@ func TestHandleInboxValidUnfollow(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
@ -465,7 +465,7 @@ func TestHandleInboxValidUnfollow(t *testing.T) {
if res != 0 {
t.Fatalf("Failed - Subscription not succeed.")
}
exportConfig.DelSubscription(domain.Host)
relayState.DelSubscription(domain.Host)
}
func TestHandleInboxInvalidUnfollow(t *testing.T) {
@ -477,7 +477,7 @@ func TestHandleInboxInvalidUnfollow(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
@ -495,7 +495,7 @@ func TestHandleInboxInvalidUnfollow(t *testing.T) {
if res != 1 {
t.Fatalf("Failed - Block hacked unfollow not succeed.")
}
exportConfig.DelSubscription(domain.Host)
relayState.DelSubscription(domain.Host)
}
func TestHandleInboxUnfollowAsActor(t *testing.T) {
@ -507,7 +507,7 @@ func TestHandleInboxUnfollowAsActor(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
@ -525,7 +525,7 @@ func TestHandleInboxUnfollowAsActor(t *testing.T) {
if res != 1 {
t.Fatalf("Failed - Block actor unfollow not succeed.")
}
exportConfig.DelSubscription(domain.Host)
relayState.DelSubscription(domain.Host)
}
func TestHandleInboxValidCreate(t *testing.T) {
@ -537,11 +537,11 @@ func TestHandleInboxValidCreate(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: "example.org",
InboxURL: "https://example.org/inbox",
})
@ -555,8 +555,8 @@ func TestHandleInboxValidCreate(t *testing.T) {
if r.StatusCode != 202 {
t.Fatalf("Failed - StatusCode is not 202 - " + strconv.Itoa(r.StatusCode))
}
exportConfig.DelSubscription(domain.Host)
exportConfig.DelSubscription("example.org")
relayState.DelSubscription(domain.Host)
relayState.DelSubscription("example.org")
redClient.Del("relay:subscription:" + domain.Host).Result()
redClient.Del("relay:subscription:example.org").Result()
}
@ -570,11 +570,11 @@ func TestHandleInboxlimitedCreate(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
exportConfig.SetLimitedDomain(domain.Host, true)
relayState.SetLimitedDomain(domain.Host, true)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -585,8 +585,8 @@ func TestHandleInboxlimitedCreate(t *testing.T) {
if r.StatusCode != 202 {
t.Fatalf("Failed - StatusCode is not 202 - " + strconv.Itoa(r.StatusCode))
}
exportConfig.DelSubscription(domain.Host)
exportConfig.SetLimitedDomain(domain.Host, false)
relayState.DelSubscription(domain.Host)
relayState.SetLimitedDomain(domain.Host, false)
}
func TestHandleInboxValidCreateAsAnnounceNote(t *testing.T) {
@ -598,15 +598,15 @@ func TestHandleInboxValidCreateAsAnnounceNote(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: "example.org",
InboxURL: "https://example.org/inbox",
})
exportConfig.SetConfig(CreateAsAnnounce, true)
relayState.SetConfig(CreateAsAnnounce, true)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -617,9 +617,9 @@ func TestHandleInboxValidCreateAsAnnounceNote(t *testing.T) {
if r.StatusCode != 202 {
t.Fatalf("Failed - StatusCode is not 202 - " + strconv.Itoa(r.StatusCode))
}
exportConfig.DelSubscription(domain.Host)
exportConfig.DelSubscription("example.org")
exportConfig.SetConfig(CreateAsAnnounce, false)
relayState.DelSubscription(domain.Host)
relayState.DelSubscription("example.org")
relayState.SetConfig(CreateAsAnnounce, false)
}
func TestHandleInboxValidCreateAsAnnounceNoNote(t *testing.T) {
@ -631,15 +631,15 @@ func TestHandleInboxValidCreateAsAnnounceNoNote(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: "example.org",
InboxURL: "https://example.org/inbox",
})
exportConfig.SetConfig(CreateAsAnnounce, true)
relayState.SetConfig(CreateAsAnnounce, true)
req, _ := http.NewRequest("POST", s.URL, nil)
client := new(http.Client)
@ -650,9 +650,9 @@ func TestHandleInboxValidCreateAsAnnounceNoNote(t *testing.T) {
if r.StatusCode != 202 {
t.Fatalf("Failed - StatusCode is not 202 - " + strconv.Itoa(r.StatusCode))
}
exportConfig.DelSubscription(domain.Host)
exportConfig.DelSubscription("example.org")
exportConfig.SetConfig(CreateAsAnnounce, false)
relayState.DelSubscription(domain.Host)
relayState.DelSubscription("example.org")
relayState.SetConfig(CreateAsAnnounce, false)
}
func TestHandleInboxUnsubscriptionCreate(t *testing.T) {
@ -683,7 +683,7 @@ func TestHandleInboxUndo(t *testing.T) {
}))
defer s.Close()
exportConfig.AddSubscription(relayconf.Subscription{
relayState.AddSubscription(state.Subscription{
Domain: domain.Host,
InboxURL: "https://mastodon.test.yukimochi.io/inbox",
})
@ -701,5 +701,5 @@ func TestHandleInboxUndo(t *testing.T) {
if res != 1 {
t.Fatalf("Failed - Missing unsubscribed.")
}
exportConfig.DelSubscription(domain.Host)
relayState.DelSubscription(domain.Host)
}

View File

@ -12,7 +12,7 @@ import (
"github.com/go-redis/redis"
"github.com/yukimochi/Activity-Relay/ActivityPub"
"github.com/yukimochi/Activity-Relay/KeyLoader"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
// Actor : Relay's Actor
@ -25,7 +25,7 @@ var hostname *url.URL
var hostkey *rsa.PrivateKey
var redClient *redis.Client
var macServer *machinery.Server
var exportConfig relayconf.ExportConfig
var relayState state.RelayState
func main() {
pemPath := os.Getenv("ACTOR_PEM")
@ -74,7 +74,7 @@ func main() {
WebfingerResource.GenerateFromActor(hostname, &Actor)
// Load Config
exportConfig = relayconf.NewConfig(redClient)
relayState = state.NewState(redClient)
http.HandleFunc("/.well-known/webfinger", handleWebfinger)
http.HandleFunc("/actor", handleActor)

View File

@ -9,7 +9,7 @@ import (
"github.com/RichardKnop/machinery/v1/config"
"github.com/go-redis/redis"
"github.com/yukimochi/Activity-Relay/KeyLoader"
"github.com/yukimochi/Activity-Relay/RelayConf"
"github.com/yukimochi/Activity-Relay/State"
)
func TestMain(m *testing.M) {
@ -36,7 +36,7 @@ func TestMain(m *testing.M) {
// Load Config
redClient.FlushAll().Result()
exportConfig = relayconf.NewConfig(redClient)
relayState = state.NewState(redClient)
code := m.Run()
os.Exit(code)
redClient.FlushAll().Result()