gitforge/services/packages/perm.go
limiting-factor f46082c3b2
chore: move determinePackageAccessMode from context packages
It allows it to be called in isolation for testing purposes, when
no context is available.
2026-06-20 06:24:07 +02:00

72 lines
2.2 KiB
Go

// Copyright 2026 The Forgejo Authors.
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package packages
import (
"context"
"forgejo.org/models/organization"
"forgejo.org/models/perm"
"forgejo.org/models/unit"
user_model "forgejo.org/models/user"
"forgejo.org/modules/setting"
api "forgejo.org/modules/structs"
)
func DeterminePackageAccessMode(ctx context.Context, owner, doer *user_model.User) (perm.AccessMode, error) {
if setting.Service.RequireSignInView && (doer == nil || doer.IsGhost()) {
return perm.AccessModeNone, nil
}
if doer != nil && !doer.IsGhost() && !doer.IsAccessAllowed(ctx) {
return perm.AccessModeNone, nil
}
// TODO: ActionUser permission check
accessMode := perm.AccessModeNone
if owner.IsOrganization() {
org := organization.OrgFromUser(owner)
if doer != nil && !doer.IsGhost() {
// 1. If user is logged in, check all team packages permissions
var err error
accessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx, doer.ID)
if err != nil {
return accessMode, err
}
// If access mode is less than write check every team for more permissions
// The minimum possible access mode is read for org members
if accessMode < perm.AccessModeWrite {
teams, err := organization.GetUserOrgTeams(ctx, org.ID, doer.ID)
if err != nil {
return accessMode, err
}
for _, t := range teams {
perm := t.UnitAccessMode(ctx, unit.TypePackages)
if accessMode < perm {
accessMode = perm
}
}
}
}
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, owner, doer) {
// 2. If user is unauthorized or no org member, check if org is visible
accessMode = perm.AccessModeRead
}
} else {
if doer != nil && !doer.IsGhost() {
// 1. Check if user is package owner
if doer.ID == owner.ID {
accessMode = perm.AccessModeOwner
} else if owner.Visibility == api.VisibleTypePublic || owner.Visibility == api.VisibleTypeLimited { // 2. Check if package owner is public or limited
accessMode = perm.AccessModeRead
}
} else if owner.Visibility == api.VisibleTypePublic { // 3. Check if package owner is public
accessMode = perm.AccessModeRead
}
}
return accessMode, nil
}