finger.go (2741B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package dereferencing 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "net/url" 26 "strings" 27 28 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 29 "github.com/superseriousbusiness/gotosocial/internal/transport" 30 "github.com/superseriousbusiness/gotosocial/internal/util" 31 ) 32 33 func (d *deref) fingerRemoteAccount(ctx context.Context, transport transport.Transport, targetUsername string, targetHost string) (accountDomain string, accountURI *url.URL, err error) { 34 b, err := transport.Finger(ctx, targetUsername, targetHost) 35 if err != nil { 36 err = fmt.Errorf("fingerRemoteAccount: error fingering @%s@%s: %s", targetUsername, targetHost, err) 37 return 38 } 39 40 resp := &apimodel.WellKnownResponse{} 41 if err = json.Unmarshal(b, resp); err != nil { 42 err = fmt.Errorf("fingerRemoteAccount: could not unmarshal server response as WebfingerAccountResponse while dereferencing @%s@%s: %s", targetUsername, targetHost, err) 43 return 44 } 45 46 if len(resp.Links) == 0 { 47 err = fmt.Errorf("fingerRemoteAccount: no links found in webfinger response %s", string(b)) 48 return 49 } 50 51 if resp.Subject == "" { 52 err = fmt.Errorf("fingerRemoteAccount: no subject found in webfinger response %s", string(b)) 53 return 54 } 55 56 _, accountDomain, err = util.ExtractWebfingerParts(resp.Subject) 57 if err != nil { 58 err = fmt.Errorf("fingerRemoteAccount: error extracting webfinger subject parts: %s", err) 59 } 60 61 // look through the links for the first one that matches what we need 62 for _, l := range resp.Links { 63 if l.Rel == "self" && (strings.EqualFold(l.Type, "application/activity+json") || strings.EqualFold(l.Type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")) { 64 if uri, thiserr := url.Parse(l.Href); thiserr == nil && (uri.Scheme == "http" || uri.Scheme == "https") { 65 // found it! 66 accountURI = uri 67 return 68 } 69 } 70 } 71 72 return "", nil, errors.New("fingerRemoteAccount: no match found in webfinger response") 73 }