Skip to content

Commit e60158c

Browse files
author
Anthony Wang
committed
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.
1 parent add8469 commit e60158c

File tree

5 files changed

+16
-23
lines changed

5 files changed

+16
-23
lines changed

integrations/webfinger_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestWebfinger(t *testing.T) {
5252
var jrd webfingerJRD
5353
DecodeJSON(t, resp, &jrd)
5454
assert.Equal(t, "acct:user2@"+appURL.Host, jrd.Subject)
55-
assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user/" + user.Name}, jrd.Aliases)
55+
assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(user.Name)}, jrd.Aliases)
5656

5757
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", user.LowerName, "unknown.host"))
5858
MakeRequest(t, req, http.StatusBadRequest)

routers/api/v1/activitypub/person.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ package activitypub
66

77
import (
88
"net/http"
9-
"strings"
109

1110
"code.gitea.io/gitea/modules/activitypub"
1211
"code.gitea.io/gitea/modules/context"
1312
"code.gitea.io/gitea/modules/json"
1413
"code.gitea.io/gitea/modules/log"
1514
"code.gitea.io/gitea/modules/setting"
16-
"code.gitea.io/gitea/routers/api/v1/user"
1715

1816
ap "github.com/go-ap/activitypub"
1917
)
@@ -35,35 +33,29 @@ func Person(ctx *context.APIContext) {
3533
// "200":
3634
// "$ref": "#/responses/ActivityPub"
3735

38-
user := user.GetUserByParamsName(ctx, "username")
39-
if user == nil {
40-
return
41-
}
42-
username := ctx.Params("username")
43-
44-
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
36+
link := setting.AppURL + "api/v1/activitypub/user/" + ctx.ContextUser.Name
4537
person := ap.PersonNew(ap.IRI(link))
4638

4739
person.Name = ap.NaturalLanguageValuesNew()
48-
err := person.Name.Set("en", ap.Content(user.FullName))
40+
err := person.Name.Set("en", ap.Content(ctx.ContextUser.FullName))
4941
if err != nil {
5042
ctx.Error(http.StatusInternalServerError, "Set Name", err)
5143
return
5244
}
5345

5446
person.PreferredUsername = ap.NaturalLanguageValuesNew()
55-
err = person.PreferredUsername.Set("en", ap.Content(username))
47+
err = person.PreferredUsername.Set("en", ap.Content(ctx.ContextUser.Name))
5648
if err != nil {
5749
ctx.Error(http.StatusInternalServerError, "Set PreferredUsername", err)
5850
return
5951
}
6052

61-
person.URL = ap.IRI(setting.AppURL + username)
53+
person.URL = ap.IRI(ctx.ContextUser.HTMLURL())
6254

6355
person.Icon = ap.Image{
6456
Type: ap.ImageType,
6557
MediaType: "image/png",
66-
URL: ap.IRI(user.AvatarLink()),
58+
URL: ap.IRI(ctx.ContextUser.AvatarLink()),
6759
}
6860

6961
person.Inbox = nil
@@ -74,7 +66,7 @@ func Person(ctx *context.APIContext) {
7466
person.PublicKey.ID = ap.IRI(link + "#main-key")
7567
person.PublicKey.Owner = ap.IRI(link)
7668

77-
publicKeyPem, err := activitypub.GetPublicKey(user)
69+
publicKeyPem, err := activitypub.GetPublicKey(ctx.ContextUser)
7870
if err != nil {
7971
ctx.Error(http.StatusInternalServerError, "GetPublicKey", err)
8072
return
@@ -84,12 +76,14 @@ func Person(ctx *context.APIContext) {
8476
binary, err := person.MarshalJSON()
8577
if err != nil {
8678
ctx.Error(http.StatusInternalServerError, "Serialize", err)
79+
return
8780
}
8881

8982
var jsonmap map[string]interface{}
9083
err = json.Unmarshal(binary, &jsonmap)
9184
if err != nil {
92-
ctx.Error(http.StatusInternalServerError, "Unmarshall", err)
85+
ctx.Error(http.StatusInternalServerError, "Unmarshal", err)
86+
return
9387
}
9488

9589
jsonmap["@context"] = []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"}

routers/api/v1/activitypub/reqsignature.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package activitypub
66

77
import (
8-
"context"
98
"crypto"
109
"crypto/x509"
1110
"encoding/pem"
@@ -25,7 +24,7 @@ import (
2524
"github.com/go-fed/httpsig"
2625
)
2726

28-
func getPublicKeyFromResponse(ctx context.Context, b []byte, keyID *url.URL) (p crypto.PublicKey, err error) {
27+
func getPublicKeyFromResponse(b []byte, keyID *url.URL) (p crypto.PublicKey, err error) {
2928
person := ap.PersonNew(ap.IRI(keyID.String()))
3029
err = person.UnmarshalJSON(b)
3130
if err != nil {
@@ -34,7 +33,7 @@ func getPublicKeyFromResponse(ctx context.Context, b []byte, keyID *url.URL) (p
3433
}
3534
pubKey := person.PublicKey
3635
if pubKey.ID.String() != keyID.String() {
37-
err = fmt.Errorf("cannot find publicKey with id: %s in %s", keyID, b)
36+
err = fmt.Errorf("cannot find publicKey with id: %s in %s", keyID, string(b))
3837
return
3938
}
4039
pubKeyPem := pubKey.PublicKeyPem
@@ -84,7 +83,7 @@ func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, er
8483
if err != nil {
8584
return
8685
}
87-
pubKey, err := getPublicKeyFromResponse(*ctx, b, idIRI)
86+
pubKey, err := getPublicKeyFromResponse(b, idIRI)
8887
if err != nil {
8988
return
9089
}

routers/api/v1/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ func Routes() *web.Route {
648648
m.Group("/user/{username}", func() {
649649
m.Get("", activitypub.Person)
650650
m.Post("/inbox", activitypub.ReqSignature(), activitypub.PersonInbox)
651-
})
651+
}, context_service.UserAssignmentAPI())
652652
})
653653
}
654654
m.Get("/signing-key.gpg", misc.SigningKey)

routers/web/webfinger.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func WebfingerQuery(ctx *context.Context) {
8787

8888
aliases := []string{
8989
u.HTMLURL(),
90-
appURL.String() + "api/v1/activitypub/user/" + strings.ToLower(u.Name),
90+
appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(u.Name),
9191
}
9292
if !u.KeepEmailPrivate {
9393
aliases = append(aliases, fmt.Sprintf("mailto:%s", u.Email))
@@ -106,7 +106,7 @@ func WebfingerQuery(ctx *context.Context) {
106106
{
107107
Rel: "self",
108108
Type: "application/activity+json",
109-
Href: appURL.String() + "api/v1/activitypub/user/" + strings.ToLower(u.Name),
109+
Href: appURL.String() + "api/v1/activitypub/user/" + url.PathEscape(u.Name),
110110
},
111111
{
112112
Rel: "http://ostatus.org/schema/1.0/subscribe",

0 commit comments

Comments
 (0)