resolve.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package resolvers
  2. import (
  3. "context"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. "github.com/go-fed/activity/streams"
  8. "github.com/go-fed/activity/streams/vocab"
  9. "github.com/owncast/owncast/activitypub/apmodels"
  10. "github.com/owncast/owncast/activitypub/crypto"
  11. "github.com/owncast/owncast/persistence/configrepository"
  12. "github.com/pkg/errors"
  13. log "github.com/sirupsen/logrus"
  14. )
  15. // Resolve will translate a raw ActivityPub payload and fire the callback associated with that activity type.
  16. func Resolve(c context.Context, data []byte, callbacks ...interface{}) error {
  17. jsonResolver, err := streams.NewJSONResolver(callbacks...)
  18. if err != nil {
  19. // Something in the setup was wrong. For example, a callback has an
  20. // unsupported signature and would never be called
  21. return err
  22. }
  23. var jsonMap map[string]interface{}
  24. if err = json.Unmarshal(data, &jsonMap); err != nil {
  25. return err
  26. }
  27. log.Debugln("Resolving payload...", string(data))
  28. // The createCallback function will be called.
  29. err = jsonResolver.Resolve(c, jsonMap)
  30. if err != nil && !streams.IsUnmatchedErr(err) {
  31. // Something went wrong
  32. return err
  33. } else if streams.IsUnmatchedErr(err) {
  34. // Everything went right but the callback didn't match or the ActivityStreams
  35. // type is one that wasn't code generated.
  36. log.Debugln("No match: ", err)
  37. }
  38. return nil
  39. }
  40. // ResolveIRI will resolve an IRI ahd call the correct callback for the resolved type.
  41. func ResolveIRI(c context.Context, iri string, callbacks ...interface{}) error {
  42. configRepository := configrepository.Get()
  43. log.Debugln("Resolving", iri)
  44. req, _ := http.NewRequest(http.MethodGet, iri, nil)
  45. actor := apmodels.MakeLocalIRIForAccount(configRepository.GetDefaultFederationUsername())
  46. if err := crypto.SignRequest(req, nil, actor); err != nil {
  47. return err
  48. }
  49. response, err := http.DefaultClient.Do(req)
  50. if err != nil {
  51. return err
  52. }
  53. defer response.Body.Close()
  54. data, err := io.ReadAll(response.Body)
  55. if err != nil {
  56. return err
  57. }
  58. // fmt.Println(string(data))
  59. return Resolve(c, data, callbacks...)
  60. }
  61. // GetResolvedActorFromActorProperty resolve an external actor property to a
  62. // fully populated internal actor representation.
  63. func GetResolvedActorFromActorProperty(actor vocab.ActivityStreamsActorProperty) (apmodels.ActivityPubActor, error) {
  64. var err error
  65. var apActor apmodels.ActivityPubActor
  66. resolved := false
  67. if !actor.Empty() && actor.Len() > 0 && actor.At(0) != nil {
  68. // Explicitly use only the first actor that might be listed.
  69. actorObjectOrIRI := actor.At(0)
  70. var actorEntity apmodels.ExternalEntity
  71. // If the actor is an unresolved IRI then we need to resolve it.
  72. if actorObjectOrIRI.IsIRI() {
  73. iri := actorObjectOrIRI.GetIRI().String()
  74. return GetResolvedActorFromIRI(iri)
  75. }
  76. if actorObjectOrIRI.IsActivityStreamsPerson() {
  77. actorEntity = actorObjectOrIRI.GetActivityStreamsPerson()
  78. } else if actorObjectOrIRI.IsActivityStreamsService() {
  79. actorEntity = actorObjectOrIRI.GetActivityStreamsService()
  80. } else if actorObjectOrIRI.IsActivityStreamsApplication() {
  81. actorEntity = actorObjectOrIRI.GetActivityStreamsApplication()
  82. } else {
  83. err = errors.New("unrecognized external ActivityPub type: " + actorObjectOrIRI.Name())
  84. return apActor, err
  85. }
  86. // If any of the resolution or population failed then return the error.
  87. if err != nil {
  88. return apActor, err
  89. }
  90. // Convert the external AP entity into an internal actor representation.
  91. apa, e := apmodels.MakeActorFromExernalAPEntity(actorEntity)
  92. if apa != nil {
  93. apActor = *apa
  94. resolved = true
  95. }
  96. err = e
  97. }
  98. if !resolved && err == nil {
  99. err = errors.New("unknown error resolving actor from property value")
  100. }
  101. return apActor, err
  102. }
  103. // GetResolvedPublicKeyFromIRI will resolve a publicKey IRI string to a vocab.W3IDSecurityV1PublicKey.
  104. func GetResolvedPublicKeyFromIRI(publicKeyIRI string) (vocab.W3IDSecurityV1PublicKey, error) {
  105. var err error
  106. var pubkey vocab.W3IDSecurityV1PublicKey
  107. resolved := false
  108. personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
  109. if pkProp := person.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  110. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  111. if iter.IsW3IDSecurityV1PublicKey() {
  112. pubkey = iter.Get()
  113. resolved = true
  114. return nil
  115. }
  116. }
  117. }
  118. return errors.New("error deriving publickey from activitystreamsperson")
  119. }
  120. serviceCallback := func(c context.Context, service vocab.ActivityStreamsService) error {
  121. if pkProp := service.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  122. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  123. if iter.IsW3IDSecurityV1PublicKey() {
  124. pubkey = iter.Get()
  125. resolved = true
  126. return nil
  127. }
  128. }
  129. }
  130. return errors.New("error deriving publickey from activitystreamsservice")
  131. }
  132. applicationCallback := func(c context.Context, app vocab.ActivityStreamsApplication) error {
  133. if pkProp := app.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  134. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  135. if iter.IsW3IDSecurityV1PublicKey() {
  136. pubkey = iter.Get()
  137. resolved = true
  138. return nil
  139. }
  140. }
  141. }
  142. return errors.New("error deriving publickey from activitystreamsapp")
  143. }
  144. pubkeyCallback := func(c context.Context, pk vocab.W3IDSecurityV1PublicKey) error {
  145. pubkey = pk
  146. resolved = true
  147. return nil
  148. }
  149. if e := ResolveIRI(context.Background(), publicKeyIRI, personCallback, serviceCallback, applicationCallback, pubkeyCallback); e != nil {
  150. err = e
  151. }
  152. if err != nil {
  153. err = errors.Wrap(err, "error resolving publickey from iri, actor may not be valid: "+publicKeyIRI)
  154. }
  155. if !resolved {
  156. err = errors.New("error resolving publickey from iri, actor may not be valid: " + publicKeyIRI)
  157. }
  158. return pubkey, err
  159. }
  160. // GetResolvedActorFromIRI will resolve an IRI string to a fully populated actor.
  161. func GetResolvedActorFromIRI(personOrServiceIRI string) (apmodels.ActivityPubActor, error) {
  162. var err error
  163. var apActor apmodels.ActivityPubActor
  164. resolved := false
  165. personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
  166. apa, e := apmodels.MakeActorFromExernalAPEntity(person)
  167. if apa != nil {
  168. apActor = *apa
  169. resolved = true
  170. }
  171. return e
  172. }
  173. serviceCallback := func(c context.Context, service vocab.ActivityStreamsService) error {
  174. apa, e := apmodels.MakeActorFromExernalAPEntity(service)
  175. if apa != nil {
  176. apActor = *apa
  177. resolved = true
  178. }
  179. return e
  180. }
  181. applicationCallback := func(c context.Context, app vocab.ActivityStreamsApplication) error {
  182. apa, e := apmodels.MakeActorFromExernalAPEntity(app)
  183. if apa != nil {
  184. apActor = *apa
  185. resolved = true
  186. }
  187. return e
  188. }
  189. if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback, applicationCallback); e != nil {
  190. err = e
  191. }
  192. if err != nil {
  193. err = errors.Wrap(err, "error resolving actor from property value")
  194. }
  195. if !resolved {
  196. err = errors.New("error resolving actor from property value")
  197. }
  198. return apActor, err
  199. }