tavern/web/handler_wellknown.go

131 lines
3.4 KiB
Go

package web
import (
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"github.com/ngerakines/tavern/common"
"github.com/ngerakines/tavern/errors"
"github.com/ngerakines/tavern/g"
"github.com/ngerakines/tavern/storage"
)
func (h handler) nodeInfo(c *gin.Context) {
c.JSON(http.StatusOK, map[string]interface{}{
"links": []interface{}{
map[string]interface{}{
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.0",
"href": fmt.Sprintf("https://%s/nodeinfo/2.0", h.domain),
},
},
})
}
func (h handler) nodeInfoDetails(c *gin.Context) {
users, err := h.storage.CountUsers(c.Request.Context())
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
users30Days, err := h.storage.CountUsersLastMonth(c.Request.Context())
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
users183Days, err := h.storage.CountUsersLastHalfYear(c.Request.Context())
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
activities, err := h.storage.CountObjectEvents(c.Request.Context())
if err != nil {
h.internalServerErrorJSON(c, err)
return
}
c.JSON(http.StatusOK, map[string]interface{}{
"version": "2.0",
"software": map[string]interface{}{
"name": "tavern",
"version": g.Version(),
},
"protocols": []string{"activitypub"},
"usage": map[string]interface{}{
"users": map[string]interface{}{
"total": users,
"activeMonth": users30Days,
"activeHalfyear": users183Days,
},
"localPosts": activities,
},
"openRegistrations": false,
})
}
func (h handler) webFinger(c *gin.Context) {
resource := c.Query("resource")
if !strings.HasPrefix(resource, common.DomainPrefix(h.domain)) && (strings.HasPrefix(resource, "acct:") && !strings.HasSuffix(resource, fmt.Sprintf("@%s", h.domain))) {
h.logger.Debug("request for non-local resource received", zap.String("resource", resource))
h.writeJRD(c, http.StatusNotFound, nil)
return
}
h.logger.Info("webfinger request", zap.String("resource", c.Query("resource")))
foundActor, err := h.storage.GetActorByAlias(c.Request.Context(), resource)
if err != nil {
if errors.Is(err, errors.NotFoundError{}) {
h.notFoundJSON(c, nil)
return
}
h.internalServerErrorJSON(c, err)
return
}
response := storage.EmptyPayload()
response["subject"] = fmt.Sprintf("acct:%s@%s", foundActor.PreferredUsername, h.domain)
response["aliases"] = []string{
foundActor.ActorID,
}
self := storage.EmptyPayload()
self["rel"] = "self"
self["type"] = `application/activity+json`
self["href"] = foundActor.ActorID
response["links"] = []storage.Payload{self}
h.writeJRD(c, http.StatusOK, response)
}
func fingerUserDomain(input, domain string) (string, string, error) {
input = strings.TrimPrefix(input, "acct:")
domainPrefix := fmt.Sprintf("https://%s/", domain)
if strings.HasPrefix(input, domainPrefix) {
name := strings.TrimPrefix(input, common.GroupActorURLPrefix(domain))
name = strings.TrimPrefix(name, common.ActorURLPrefix(domain))
return name, domain, nil
}
parts := strings.FieldsFunc(input, func(r rune) bool {
return r == '@'
})
if len(parts) != 2 {
return "", "", errors.New("malformed resource parameter")
}
if parts[1] != domain {
return "", "", errors.New("malformed resource parameter")
}
name := strings.TrimSpace(parts[0])
if len(name) == 0 {
return "", "", errors.New("malformed resource parameter")
}
return name, domain, nil
}