mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-27 12:53:57 +01:00
Make sure API responses always refer to username in original case
Copied from what I wrote on #19133 discussion: Handling username case is a very tricky issue and I've already encountered a Mastodon <-> Gitea federation bug due to Gitea considering Ta180m and ta180m to be the same user while Mastodon thinks they are two different users. I think the best way forward is for Gitea to only use the original case version of the username for federation so other AP software don't get confused.
This commit is contained in:
parent
add8469813
commit
e60158c70b
5 changed files with 16 additions and 23 deletions
|
@ -52,7 +52,7 @@ func TestWebfinger(t *testing.T) {
|
|||
var jrd webfingerJRD
|
||||
DecodeJSON(t, resp, &jrd)
|
||||
assert.Equal(t, "acct:user2@"+appURL.Host, jrd.Subject)
|
||||
assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user/" + user.Name}, jrd.Aliases)
|
||||
assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(user.Name)}, jrd.Aliases)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", user.LowerName, "unknown.host"))
|
||||
MakeRequest(t, req, http.StatusBadRequest)
|
||||
|
|
|
@ -6,14 +6,12 @@ package activitypub
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/activitypub"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/routers/api/v1/user"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
)
|
||||
|
@ -35,35 +33,29 @@ func Person(ctx *context.APIContext) {
|
|||
// "200":
|
||||
// "$ref": "#/responses/ActivityPub"
|
||||
|
||||
user := user.GetUserByParamsName(ctx, "username")
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
username := ctx.Params("username")
|
||||
|
||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
||||
link := setting.AppURL + "api/v1/activitypub/user/" + ctx.ContextUser.Name
|
||||
person := ap.PersonNew(ap.IRI(link))
|
||||
|
||||
person.Name = ap.NaturalLanguageValuesNew()
|
||||
err := person.Name.Set("en", ap.Content(user.FullName))
|
||||
err := person.Name.Set("en", ap.Content(ctx.ContextUser.FullName))
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "Set Name", err)
|
||||
return
|
||||
}
|
||||
|
||||
person.PreferredUsername = ap.NaturalLanguageValuesNew()
|
||||
err = person.PreferredUsername.Set("en", ap.Content(username))
|
||||
err = person.PreferredUsername.Set("en", ap.Content(ctx.ContextUser.Name))
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "Set PreferredUsername", err)
|
||||
return
|
||||
}
|
||||
|
||||
person.URL = ap.IRI(setting.AppURL + username)
|
||||
person.URL = ap.IRI(ctx.ContextUser.HTMLURL())
|
||||
|
||||
person.Icon = ap.Image{
|
||||
Type: ap.ImageType,
|
||||
MediaType: "image/png",
|
||||
URL: ap.IRI(user.AvatarLink()),
|
||||
URL: ap.IRI(ctx.ContextUser.AvatarLink()),
|
||||
}
|
||||
|
||||
person.Inbox = nil
|
||||
|
@ -74,7 +66,7 @@ func Person(ctx *context.APIContext) {
|
|||
person.PublicKey.ID = ap.IRI(link + "#main-key")
|
||||
person.PublicKey.Owner = ap.IRI(link)
|
||||
|
||||
publicKeyPem, err := activitypub.GetPublicKey(user)
|
||||
publicKeyPem, err := activitypub.GetPublicKey(ctx.ContextUser)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPublicKey", err)
|
||||
return
|
||||
|
@ -84,12 +76,14 @@ func Person(ctx *context.APIContext) {
|
|||
binary, err := person.MarshalJSON()
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "Serialize", err)
|
||||
return
|
||||
}
|
||||
|
||||
var jsonmap map[string]interface{}
|
||||
err = json.Unmarshal(binary, &jsonmap)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "Unmarshall", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Unmarshal", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonmap["@context"] = []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
@ -25,7 +24,7 @@ import (
|
|||
"github.com/go-fed/httpsig"
|
||||
)
|
||||
|
||||
func getPublicKeyFromResponse(ctx context.Context, b []byte, keyID *url.URL) (p crypto.PublicKey, err error) {
|
||||
func getPublicKeyFromResponse(b []byte, keyID *url.URL) (p crypto.PublicKey, err error) {
|
||||
person := ap.PersonNew(ap.IRI(keyID.String()))
|
||||
err = person.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
|
@ -34,7 +33,7 @@ func getPublicKeyFromResponse(ctx context.Context, b []byte, keyID *url.URL) (p
|
|||
}
|
||||
pubKey := person.PublicKey
|
||||
if pubKey.ID.String() != keyID.String() {
|
||||
err = fmt.Errorf("cannot find publicKey with id: %s in %s", keyID, b)
|
||||
err = fmt.Errorf("cannot find publicKey with id: %s in %s", keyID, string(b))
|
||||
return
|
||||
}
|
||||
pubKeyPem := pubKey.PublicKeyPem
|
||||
|
@ -84,7 +83,7 @@ func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, er
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
pubKey, err := getPublicKeyFromResponse(*ctx, b, idIRI)
|
||||
pubKey, err := getPublicKeyFromResponse(b, idIRI)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -648,7 +648,7 @@ func Routes() *web.Route {
|
|||
m.Group("/user/{username}", func() {
|
||||
m.Get("", activitypub.Person)
|
||||
m.Post("/inbox", activitypub.ReqSignature(), activitypub.PersonInbox)
|
||||
})
|
||||
}, context_service.UserAssignmentAPI())
|
||||
})
|
||||
}
|
||||
m.Get("/signing-key.gpg", misc.SigningKey)
|
||||
|
|
|
@ -87,7 +87,7 @@ func WebfingerQuery(ctx *context.Context) {
|
|||
|
||||
aliases := []string{
|
||||
u.HTMLURL(),
|
||||
appURL.String() + "api/v1/activitypub/user/" + strings.ToLower(u.Name),
|
||||
appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(u.Name),
|
||||
}
|
||||
if !u.KeepEmailPrivate {
|
||||
aliases = append(aliases, fmt.Sprintf("mailto:%s", u.Email))
|
||||
|
@ -106,7 +106,7 @@ func WebfingerQuery(ctx *context.Context) {
|
|||
{
|
||||
Rel: "self",
|
||||
Type: "application/activity+json",
|
||||
Href: appURL.String() + "api/v1/activitypub/user/" + strings.ToLower(u.Name),
|
||||
Href: appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(u.Name),
|
||||
},
|
||||
{
|
||||
Rel: "http://ostatus.org/schema/1.0/subscribe",
|
||||
|
|
Loading…
Reference in a new issue