Support federative Add and Remove

このコミットが含まれているのは:
Cory Slep 2018-03-30 19:39:07 +02:00
コミット 6e343f9f45
2個のファイルの変更129行の追加4行の削除

ファイルの表示

@ -944,18 +944,136 @@ func (f *federator) handleReject(c context.Context) func(s *streams.Reject) erro
func (f *federator) handleAdd(c context.Context) func(s *streams.Add) error {
return func(s *streams.Add) error {
// TODO: Implement.
// Add is client application specific, generally involving adding an
// 'object' to a specific 'target' collection.
if s.LenObject() == 0 {
return ErrObjectRequired
} else if s.LenType() == 0 {
return ErrTypeRequired
}
raw := s.Raw()
ids, err := getTargetIds(raw)
if err != nil {
return err
} else if len(ids) == 0 {
return fmt.Errorf("add target has no ids: %v", s)
}
objIds, err := getObjectIds(s.Raw())
if err != nil {
return err
} else if len(objIds) == 0 {
return fmt.Errorf("add object has no ids: %v", s)
}
var targets []vocab.ObjectType
for _, id := range ids {
if !f.FederateApp.Owns(c, id) {
continue
}
target, err := f.App.Get(c, id)
if err != nil {
return err
}
ct, okCollection := target.(vocab.CollectionType)
oct, okOrdered := target.(vocab.OrderedCollectionType)
if !okCollection && !okOrdered {
return fmt.Errorf("cannot add to type that is not Collection and not OrderedCollection: %v", target)
} else if okCollection {
targets = append(targets, ct)
} else {
targets = append(targets, oct)
}
}
for i := 0; i < raw.ObjectLen(); i++ {
if !raw.IsObject(i) {
// TODO: Fetch IRIs as well
return fmt.Errorf("add object must be object type: %v", raw)
}
obj := raw.GetObject(i)
if !f.FederateApp.Owns(c, obj.GetId()) {
continue
}
for _, target := range targets {
if !f.FederateApp.CanAdd(c, obj, target) {
continue
}
if ct, ok := target.(vocab.CollectionType); ok {
ct.AddItemsObject(obj)
} else if oct, ok := target.(vocab.OrderedCollectionType); ok {
oct.AddOrderedItemsObject(obj)
}
if err := f.App.Set(c, target); err != nil {
return err
}
}
}
return f.ServerCallbacker.Add(c, s)
}
}
func (f *federator) handleRemove(c context.Context) func(s *streams.Remove) error {
return func(s *streams.Remove) error {
// TODO: Implement.
// Remove is client application specific, generally involving removing
// an 'object' from a specific 'target' collection.
if s.LenObject() == 0 {
return ErrObjectRequired
} else if s.LenType() == 0 {
return ErrTypeRequired
}
raw := s.Raw()
ids, err := getTargetIds(raw)
if err != nil {
return err
} else if len(ids) == 0 {
return fmt.Errorf("remove target has no ids: %v", s)
}
objIds, err := getObjectIds(s.Raw())
if err != nil {
return err
} else if len(objIds) == 0 {
return fmt.Errorf("remove object has no ids: %v", s)
}
var targets []vocab.ObjectType
for _, id := range ids {
if !f.FederateApp.Owns(c, id) {
continue
}
target, err := f.App.Get(c, id)
if err != nil {
return err
}
ct, okCollection := target.(vocab.CollectionType)
oct, okOrdered := target.(vocab.OrderedCollectionType)
if !okCollection && !okOrdered {
return fmt.Errorf("cannot remove from type that is not Collection and not OrderedCollection: %v", target)
} else if okCollection {
targets = append(targets, ct)
} else {
targets = append(targets, oct)
}
}
for i := 0; i < raw.ObjectLen(); i++ {
if !raw.IsObject(i) {
// TODO: Fetch IRIs as well
return fmt.Errorf("remove object must be object type: %v", raw)
}
obj := raw.GetObject(i)
if !f.FederateApp.Owns(c, obj.GetId()) {
continue
}
for _, target := range targets {
if !f.FederateApp.CanRemove(c, obj, target) {
continue
}
if ct, ok := target.(vocab.CollectionType); ok {
removeCollectionItemWithId(ct, obj.GetId())
} else if oct, ok := target.(vocab.OrderedCollectionType); ok {
removeOrderedCollectionItemWithId(oct, obj.GetId())
}
if err := f.App.Set(c, target); err != nil {
return err
}
}
}
return f.ServerCallbacker.Remove(c, s)
}
}

ファイルの表示

@ -73,6 +73,14 @@ type SocialApp interface {
// FederateApp is provided by users of this library and designed to handle
// receiving messages from ActivityPub servers through the Federative API.
type FederateApp interface {
// Owns returns true if the provided id is owned by this server.
Owns(c context.Context, id url.URL) bool
// CanAdd returns true if the provided object is allowed to be added to
// the given target collection.
CanAdd(c context.Context, obj vocab.ObjectType, target vocab.ObjectType) bool
// CanRemove returns true if the provided object is allowed to be added to
// the given target collection.
CanRemove(c context.Context, obj vocab.ObjectType, target vocab.ObjectType) bool
// OnFollow determines whether to take any automatic reactions in
// response to this follow.
OnFollow(c context.Context, s *streams.Follow) FollowResponse
@ -155,11 +163,10 @@ type Callbacker interface {
// PubObject is an ActivityPub Object.
type PubObject interface {
Typer
GetId() url.URL
SetId(url.URL)
HasId() bool
TypeLen() int
GetType(int) interface{}
AddType(interface{})
RemoveType(int)
}