mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
fix: hide user profile anonymous options on public repo APIs
This commit is contained in:
parent
0fe80e0110
commit
f7442ac4c7
3 changed files with 50 additions and 5 deletions
|
|
@ -46,6 +46,7 @@
|
|||
email: user2@example.com
|
||||
keep_email_private: true
|
||||
keep_pronouns_private: true
|
||||
pronouns: he/him
|
||||
email_notifications_preference: enabled
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"context"
|
||||
stdCtx "context"
|
||||
"time"
|
||||
|
||||
"forgejo.org/models"
|
||||
|
|
@ -15,14 +15,15 @@ import (
|
|||
unit_model "forgejo.org/models/unit"
|
||||
"forgejo.org/modules/log"
|
||||
api "forgejo.org/modules/structs"
|
||||
"forgejo.org/services/context"
|
||||
)
|
||||
|
||||
// ToRepo converts a Repository to api.Repository
|
||||
func ToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission) *api.Repository {
|
||||
func ToRepo(ctx stdCtx.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission) *api.Repository {
|
||||
return innerToRepo(ctx, repo, permissionInRepo, false)
|
||||
}
|
||||
|
||||
func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission, isParent bool) *api.Repository {
|
||||
func innerToRepo(ctx stdCtx.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission, isParent bool) *api.Repository {
|
||||
var parent *api.Repository
|
||||
|
||||
if permissionInRepo.Units == nil && permissionInRepo.UnitsMode == nil {
|
||||
|
|
@ -179,9 +180,19 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
|||
|
||||
repoAPIURL := repo.APIURL()
|
||||
|
||||
// Calculate the effective permission for `ToUserWithAccessMode` for the repo owner. When accessing a public repo,
|
||||
// permissionInRepo.AccessMode will be AccessModeRead even for an anonymous user -- in that case, downgrade
|
||||
// `ownerViewPerms` to `AccessModeNone`. `innerToRepo` doesn't have great access to recognize an anonymous user, so
|
||||
// the best-effort made here is to check if `ctx` is an `APIContext`.
|
||||
ownerViewPerms := permissionInRepo.AccessMode
|
||||
apiCtx, ok := ctx.(*context.APIContext)
|
||||
if ok && apiCtx.Doer == nil {
|
||||
ownerViewPerms = perm.AccessModeNone
|
||||
}
|
||||
|
||||
return &api.Repository{
|
||||
ID: repo.ID,
|
||||
Owner: ToUserWithAccessMode(ctx, repo.Owner, permissionInRepo.AccessMode),
|
||||
Owner: ToUserWithAccessMode(ctx, repo.Owner, ownerViewPerms),
|
||||
Name: repo.Name,
|
||||
FullName: repo.FullName(),
|
||||
Description: repo.Description,
|
||||
|
|
@ -246,7 +257,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
|||
}
|
||||
|
||||
// ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer
|
||||
func ToRepoTransfer(ctx context.Context, t *models.RepoTransfer) *api.RepoTransfer {
|
||||
func ToRepoTransfer(ctx stdCtx.Context, t *models.RepoTransfer) *api.RepoTransfer {
|
||||
teams, _ := ToTeams(ctx, t.Teams, false)
|
||||
|
||||
return &api.RepoTransfer{
|
||||
|
|
|
|||
|
|
@ -289,6 +289,39 @@ func TestAPIViewRepo(t *testing.T) {
|
|||
assert.Equal(t, 1, repo.Stars)
|
||||
}
|
||||
|
||||
// Validate that private information on the user profile isn't exposed by way of being an owner of a public repository.
|
||||
func TestAPIViewRepoOwnerSettings(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
var repo api.Repository
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.EqualValues(t, 1, repo.ID)
|
||||
assert.Equal(t, "user2@noreply.example.org", repo.Owner.Email) // unauthed, always private
|
||||
assert.Empty(t, repo.Owner.Pronouns) // user2.keep_pronouns_private = true
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1").AddTokenAuth(token)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.Equal(t, "user2@noreply.example.org", repo.Owner.Email) // user2.keep_email_private = true
|
||||
assert.Equal(t, "he/him", repo.Owner.Pronouns) // user2.keep_pronouns_private = true
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/repos/user12/repo10")
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.EqualValues(t, 10, repo.ID)
|
||||
assert.Equal(t, "user12@noreply.example.org", repo.Owner.Email) // unauthed, always private
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/repos/user12/repo10").AddTokenAuth(token)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.Equal(t, "user12@example.com", repo.Owner.Email) // user2.keep_email_private = false
|
||||
}
|
||||
|
||||
func TestAPIOrgRepos(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue