wellknown.go (4808B)
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 fedi 19 20 import ( 21 "context" 22 "fmt" 23 24 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 25 "github.com/superseriousbusiness/gotosocial/internal/config" 26 "github.com/superseriousbusiness/gotosocial/internal/gtserror" 27 ) 28 29 const ( 30 hostMetaXMLNS = "http://docs.oasis-open.org/ns/xri/xrd-1.0" 31 hostMetaRel = "lrdd" 32 hostMetaType = "application/xrd+xml" 33 hostMetaTemplate = ".well-known/webfinger?resource={uri}" 34 nodeInfoVersion = "2.0" 35 nodeInfoSoftwareName = "gotosocial" 36 nodeInfoRel = "http://nodeinfo.diaspora.software/ns/schema/" + nodeInfoVersion 37 webfingerProfilePage = "http://webfinger.net/rel/profile-page" 38 webFingerProfilePageContentType = "text/html" 39 webfingerSelf = "self" 40 webFingerSelfContentType = "application/activity+json" 41 webfingerAccount = "acct" 42 ) 43 44 var ( 45 nodeInfoProtocols = []string{"activitypub"} 46 nodeInfoInbound = []string{} 47 nodeInfoOutbound = []string{} 48 nodeInfoMetadata = make(map[string]interface{}) 49 ) 50 51 // NodeInfoRelGet returns a well known response giving the path to node info. 52 func (p *Processor) NodeInfoRelGet(ctx context.Context) (*apimodel.WellKnownResponse, gtserror.WithCode) { 53 protocol := config.GetProtocol() 54 host := config.GetHost() 55 56 return &apimodel.WellKnownResponse{ 57 Links: []apimodel.Link{ 58 { 59 Rel: nodeInfoRel, 60 Href: fmt.Sprintf("%s://%s/nodeinfo/%s", protocol, host, nodeInfoVersion), 61 }, 62 }, 63 }, nil 64 } 65 66 // NodeInfoGet returns a node info struct in response to a node info request. 67 func (p *Processor) NodeInfoGet(ctx context.Context) (*apimodel.Nodeinfo, gtserror.WithCode) { 68 host := config.GetHost() 69 70 userCount, err := p.state.DB.CountInstanceUsers(ctx, host) 71 if err != nil { 72 return nil, gtserror.NewErrorInternalError(err) 73 } 74 75 postCount, err := p.state.DB.CountInstanceStatuses(ctx, host) 76 if err != nil { 77 return nil, gtserror.NewErrorInternalError(err) 78 } 79 80 return &apimodel.Nodeinfo{ 81 Version: nodeInfoVersion, 82 Software: apimodel.NodeInfoSoftware{ 83 Name: nodeInfoSoftwareName, 84 Version: config.GetSoftwareVersion(), 85 }, 86 Protocols: nodeInfoProtocols, 87 Services: apimodel.NodeInfoServices{ 88 Inbound: nodeInfoInbound, 89 Outbound: nodeInfoOutbound, 90 }, 91 OpenRegistrations: config.GetAccountsRegistrationOpen(), 92 Usage: apimodel.NodeInfoUsage{ 93 Users: apimodel.NodeInfoUsers{ 94 Total: userCount, 95 }, 96 LocalPosts: postCount, 97 }, 98 Metadata: nodeInfoMetadata, 99 }, nil 100 } 101 102 // HostMetaGet returns a host-meta struct in response to a host-meta request. 103 func (p *Processor) HostMetaGet() *apimodel.HostMeta { 104 protocol := config.GetProtocol() 105 host := config.GetHost() 106 return &apimodel.HostMeta{ 107 XMLNS: hostMetaXMLNS, 108 Link: []apimodel.Link{ 109 { 110 Rel: hostMetaRel, 111 Type: hostMetaType, 112 Template: fmt.Sprintf("%s://%s/%s", protocol, host, hostMetaTemplate), 113 }, 114 }, 115 } 116 } 117 118 // WebfingerGet handles the GET for a webfinger resource. Most commonly, it will be used for returning account lookups. 119 func (p *Processor) WebfingerGet(ctx context.Context, requestedUsername string) (*apimodel.WellKnownResponse, gtserror.WithCode) { 120 // Get the local account the request is referring to. 121 requestedAccount, err := p.state.DB.GetAccountByUsernameDomain(ctx, requestedUsername, "") 122 if err != nil { 123 return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err)) 124 } 125 126 return &apimodel.WellKnownResponse{ 127 Subject: webfingerAccount + ":" + requestedAccount.Username + "@" + config.GetAccountDomain(), 128 Aliases: []string{ 129 requestedAccount.URI, 130 requestedAccount.URL, 131 }, 132 Links: []apimodel.Link{ 133 { 134 Rel: webfingerProfilePage, 135 Type: webFingerProfilePageContentType, 136 Href: requestedAccount.URL, 137 }, 138 { 139 Rel: webfingerSelf, 140 Type: webFingerSelfContentType, 141 Href: requestedAccount.URI, 142 }, 143 }, 144 }, nil 145 }