mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Follow #33127 Fix #8649, fix #639 This is a complete solution. A repo unit could be set to: * Anonymous read (non-signed-in user) * Everyone read (signed-in user) * Everyone write (wiki-only)
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2025 The Gitea Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package setting
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"slices"
 | |
| 	"strconv"
 | |
| 
 | |
| 	"code.gitea.io/gitea/models/perm"
 | |
| 	"code.gitea.io/gitea/models/repo"
 | |
| 	"code.gitea.io/gitea/models/unit"
 | |
| 	"code.gitea.io/gitea/modules/setting"
 | |
| 	"code.gitea.io/gitea/modules/templates"
 | |
| 	"code.gitea.io/gitea/services/context"
 | |
| )
 | |
| 
 | |
| const tplRepoSettingsPublicAccess templates.TplName = "repo/settings/public_access"
 | |
| 
 | |
| func parsePublicAccessMode(permission string, allowed []string) (ret struct {
 | |
| 	AnonymousAccessMode, EveryoneAccessMode perm.AccessMode
 | |
| },
 | |
| ) {
 | |
| 	ret.AnonymousAccessMode = perm.AccessModeNone
 | |
| 	ret.EveryoneAccessMode = perm.AccessModeNone
 | |
| 
 | |
| 	// if site admin forces repositories to be private, then do not allow any other access mode,
 | |
| 	// otherwise the "force private" setting would be bypassed
 | |
| 	if setting.Repository.ForcePrivate {
 | |
| 		return ret
 | |
| 	}
 | |
| 	if !slices.Contains(allowed, permission) {
 | |
| 		return ret
 | |
| 	}
 | |
| 	switch permission {
 | |
| 	case paAnonymousRead:
 | |
| 		ret.AnonymousAccessMode = perm.AccessModeRead
 | |
| 	case paEveryoneRead:
 | |
| 		ret.EveryoneAccessMode = perm.AccessModeRead
 | |
| 	case paEveryoneWrite:
 | |
| 		ret.EveryoneAccessMode = perm.AccessModeWrite
 | |
| 	}
 | |
| 	return ret
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	paNotSet        = "not-set"
 | |
| 	paAnonymousRead = "anonymous-read"
 | |
| 	paEveryoneRead  = "everyone-read"
 | |
| 	paEveryoneWrite = "everyone-write"
 | |
| )
 | |
| 
 | |
| type repoUnitPublicAccess struct {
 | |
| 	UnitType          unit.Type
 | |
| 	FormKey           string
 | |
| 	DisplayName       string
 | |
| 	PublicAccessTypes []string
 | |
| 	UnitPublicAccess  string
 | |
| }
 | |
| 
 | |
| func repoUnitPublicAccesses(ctx *context.Context) []*repoUnitPublicAccess {
 | |
| 	accesses := []*repoUnitPublicAccess{
 | |
| 		{
 | |
| 			UnitType:          unit.TypeCode,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.code"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypeIssues,
 | |
| 			DisplayName:       ctx.Locale.TrString("issues"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypePullRequests,
 | |
| 			DisplayName:       ctx.Locale.TrString("pull_requests"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypeReleases,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.releases"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypeWiki,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.wiki"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead, paEveryoneWrite},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypeProjects,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.projects"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypePackages,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.packages"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 		{
 | |
| 			UnitType:          unit.TypeActions,
 | |
| 			DisplayName:       ctx.Locale.TrString("repo.actions"),
 | |
| 			PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
 | |
| 		},
 | |
| 	}
 | |
| 	for _, ua := range accesses {
 | |
| 		ua.FormKey = "repo-unit-access-" + strconv.Itoa(int(ua.UnitType))
 | |
| 		for _, u := range ctx.Repo.Repository.Units {
 | |
| 			if u.Type == ua.UnitType {
 | |
| 				ua.UnitPublicAccess = paNotSet
 | |
| 				switch {
 | |
| 				case u.EveryoneAccessMode == perm.AccessModeWrite:
 | |
| 					ua.UnitPublicAccess = paEveryoneWrite
 | |
| 				case u.EveryoneAccessMode == perm.AccessModeRead:
 | |
| 					ua.UnitPublicAccess = paEveryoneRead
 | |
| 				case u.AnonymousAccessMode == perm.AccessModeRead:
 | |
| 					ua.UnitPublicAccess = paAnonymousRead
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return slices.DeleteFunc(accesses, func(ua *repoUnitPublicAccess) bool {
 | |
| 		return ua.UnitPublicAccess == ""
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func PublicAccess(ctx *context.Context) {
 | |
| 	ctx.Data["PageIsSettingsPublicAccess"] = true
 | |
| 	ctx.Data["RepoUnitPublicAccesses"] = repoUnitPublicAccesses(ctx)
 | |
| 	ctx.Data["GlobalForcePrivate"] = setting.Repository.ForcePrivate
 | |
| 	if setting.Repository.ForcePrivate {
 | |
| 		ctx.Flash.Error(ctx.Tr("form.repository_force_private"), true)
 | |
| 	}
 | |
| 	ctx.HTML(http.StatusOK, tplRepoSettingsPublicAccess)
 | |
| }
 | |
| 
 | |
| func PublicAccessPost(ctx *context.Context) {
 | |
| 	accesses := repoUnitPublicAccesses(ctx)
 | |
| 	for _, ua := range accesses {
 | |
| 		formVal := ctx.FormString(ua.FormKey)
 | |
| 		parsed := parsePublicAccessMode(formVal, ua.PublicAccessTypes)
 | |
| 		err := repo.UpdateRepoUnitPublicAccess(ctx, &repo.RepoUnit{
 | |
| 			RepoID:              ctx.Repo.Repository.ID,
 | |
| 			Type:                ua.UnitType,
 | |
| 			AnonymousAccessMode: parsed.AnonymousAccessMode,
 | |
| 			EveryoneAccessMode:  parsed.EveryoneAccessMode,
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			ctx.ServerError("UpdateRepoUnitPublicAccess", err)
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
 | |
| 	ctx.Redirect(ctx.Repo.Repository.Link() + "/settings/public_access")
 | |
| }
 |