mirror of https://github.com/go-gitea/gitea.git
Add anonymous access support for private/unlisted repositories (#34051)
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)pull/34054/head
parent
49899070cd
commit
cddd19efc8
|
@ -15,6 +15,7 @@ import (
|
|||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
|
@ -50,7 +51,7 @@ func (p *Permission) HasAnyUnitAccess() bool {
|
|||
return p.AccessMode >= perm_model.AccessModeRead
|
||||
}
|
||||
|
||||
func (p *Permission) HasAnyUnitAccessOrPublicAccess() bool {
|
||||
func (p *Permission) HasAnyUnitPublicAccess() bool {
|
||||
for _, v := range p.anonymousAccessMode {
|
||||
if v >= perm_model.AccessModeRead {
|
||||
return true
|
||||
|
@ -61,7 +62,11 @@ func (p *Permission) HasAnyUnitAccessOrPublicAccess() bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
return p.HasAnyUnitAccess()
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Permission) HasAnyUnitAccessOrPublicAccess() bool {
|
||||
return p.HasAnyUnitPublicAccess() || p.HasAnyUnitAccess()
|
||||
}
|
||||
|
||||
// HasUnits returns true if the permission contains attached units
|
||||
|
@ -188,6 +193,9 @@ func (p *Permission) LogString() string {
|
|||
}
|
||||
|
||||
func applyPublicAccessPermission(unitType unit.Type, accessMode perm_model.AccessMode, modeMap *map[unit.Type]perm_model.AccessMode) {
|
||||
if setting.Repository.ForcePrivate {
|
||||
return
|
||||
}
|
||||
if accessMode >= perm_model.AccessModeRead && accessMode > (*modeMap)[unitType] {
|
||||
if *modeMap == nil {
|
||||
*modeMap = make(map[unit.Type]perm_model.AccessMode)
|
||||
|
|
|
@ -342,3 +342,9 @@ func UpdateRepoUnit(ctx context.Context, unit *RepoUnit) error {
|
|||
_, err := db.GetEngine(ctx).ID(unit.ID).Update(unit)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateRepoUnitPublicAccess(ctx context.Context, unit *RepoUnit) error {
|
||||
_, err := db.GetEngine(ctx).Where("repo_id=? AND `type`=?", unit.RepoID, unit.Type).
|
||||
Cols("anonymous_access_mode", "everyone_access_mode").Update(unit)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -926,6 +926,9 @@ permission_not_set = Not set
|
|||
permission_no_access = No Access
|
||||
permission_read = Read
|
||||
permission_write = Read and Write
|
||||
permission_anonymous_read = Anonymous Read
|
||||
permission_everyone_read = Everyone Read
|
||||
permission_everyone_write = Everyone Write
|
||||
access_token_desc = Selected token permissions limit authorization only to the corresponding <a %s>API</a> routes. Read the <a %s>documentation</a> for more information.
|
||||
at_least_one_permission = You must select at least one permission to create a token
|
||||
permissions_list = Permissions:
|
||||
|
@ -1138,6 +1141,7 @@ transfer.no_permission_to_reject = You do not have permission to reject this tra
|
|||
|
||||
desc.private = Private
|
||||
desc.public = Public
|
||||
desc.public_access = Public Access
|
||||
desc.template = Template
|
||||
desc.internal = Internal
|
||||
desc.archived = Archived
|
||||
|
@ -2133,6 +2137,7 @@ contributors.contribution_type.deletions = Deletions
|
|||
settings = Settings
|
||||
settings.desc = Settings is where you can manage the settings for the repository
|
||||
settings.options = Repository
|
||||
settings.public_access = Public Access
|
||||
settings.collaboration = Collaborators
|
||||
settings.collaboration.admin = Administrator
|
||||
settings.collaboration.write = Write
|
||||
|
@ -2179,7 +2184,6 @@ settings.advanced_settings = Advanced Settings
|
|||
settings.wiki_desc = Enable Repository Wiki
|
||||
settings.use_internal_wiki = Use Built-In Wiki
|
||||
settings.default_wiki_branch_name = Default Wiki Branch Name
|
||||
settings.default_permission_everyone_access = Default access permission for all signed-in users:
|
||||
settings.failed_to_change_default_wiki_branch = Failed to change the default wiki branch.
|
||||
settings.use_external_wiki = Use External Wiki
|
||||
settings.external_wiki_url = External Wiki URL
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
// 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")
|
||||
}
|
|
@ -13,7 +13,6 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
@ -37,6 +36,8 @@ import (
|
|||
mirror_service "code.gitea.io/gitea/services/mirror"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
wiki_service "code.gitea.io/gitea/services/wiki"
|
||||
|
||||
"xorm.io/xorm/convert"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -48,15 +49,6 @@ const (
|
|||
tplDeployKeys templates.TplName = "repo/settings/deploy_keys"
|
||||
)
|
||||
|
||||
func parseEveryoneAccessMode(permission string, allowed ...perm.AccessMode) perm.AccessMode {
|
||||
// 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 perm.AccessModeNone
|
||||
}
|
||||
return perm.ParseAccessMode(permission, allowed...)
|
||||
}
|
||||
|
||||
// SettingsCtxData is a middleware that sets all the general context data for the
|
||||
// settings template.
|
||||
func SettingsCtxData(ctx *context.Context) {
|
||||
|
@ -504,6 +496,17 @@ func handleSettingsPostPushMirrorAdd(ctx *context.Context) {
|
|||
ctx.Redirect(repo.Link() + "/settings")
|
||||
}
|
||||
|
||||
func newRepoUnit(repo *repo_model.Repository, unitType unit_model.Type, config convert.Conversion) repo_model.RepoUnit {
|
||||
repoUnit := repo_model.RepoUnit{RepoID: repo.ID, Type: unitType, Config: config}
|
||||
for _, u := range repo.Units {
|
||||
if u.Type == unitType {
|
||||
repoUnit.EveryoneAccessMode = u.EveryoneAccessMode
|
||||
repoUnit.AnonymousAccessMode = u.AnonymousAccessMode
|
||||
}
|
||||
}
|
||||
return repoUnit
|
||||
}
|
||||
|
||||
func handleSettingsPostAdvanced(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.RepoSettingForm)
|
||||
repo := ctx.Repo.Repository
|
||||
|
@ -521,11 +524,7 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
|||
}
|
||||
|
||||
if form.EnableCode && !unit_model.TypeCode.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeCode,
|
||||
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultCodeEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead),
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeCode, nil))
|
||||
} else if !unit_model.TypeCode.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeCode)
|
||||
}
|
||||
|
@ -537,21 +536,12 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeExternalWiki,
|
||||
Config: &repo_model.ExternalWikiConfig{
|
||||
ExternalWikiURL: form.ExternalWikiURL,
|
||||
},
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeExternalWiki, &repo_model.ExternalWikiConfig{
|
||||
ExternalWikiURL: form.ExternalWikiURL,
|
||||
}))
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki)
|
||||
} else if form.EnableWiki && !form.EnableExternalWiki && !unit_model.TypeWiki.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeWiki,
|
||||
Config: new(repo_model.UnitConfig),
|
||||
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultWikiEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead, perm.AccessModeWrite),
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeWiki, new(repo_model.UnitConfig)))
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki)
|
||||
} else {
|
||||
if !unit_model.TypeExternalWiki.UnitGlobalDisabled() {
|
||||
|
@ -580,28 +570,19 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
|||
ctx.Redirect(repo.Link() + "/settings")
|
||||
return
|
||||
}
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeExternalTracker,
|
||||
Config: &repo_model.ExternalTrackerConfig{
|
||||
ExternalTrackerURL: form.ExternalTrackerURL,
|
||||
ExternalTrackerFormat: form.TrackerURLFormat,
|
||||
ExternalTrackerStyle: form.TrackerIssueStyle,
|
||||
ExternalTrackerRegexpPattern: form.ExternalTrackerRegexpPattern,
|
||||
},
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeExternalTracker, &repo_model.ExternalTrackerConfig{
|
||||
ExternalTrackerURL: form.ExternalTrackerURL,
|
||||
ExternalTrackerFormat: form.TrackerURLFormat,
|
||||
ExternalTrackerStyle: form.TrackerIssueStyle,
|
||||
ExternalTrackerRegexpPattern: form.ExternalTrackerRegexpPattern,
|
||||
}))
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeIssues)
|
||||
} else if form.EnableIssues && !form.EnableExternalTracker && !unit_model.TypeIssues.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeIssues,
|
||||
Config: &repo_model.IssuesConfig{
|
||||
EnableTimetracker: form.EnableTimetracker,
|
||||
AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
|
||||
EnableDependencies: form.EnableIssueDependencies,
|
||||
},
|
||||
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultIssuesEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead),
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeIssues, &repo_model.IssuesConfig{
|
||||
EnableTimetracker: form.EnableTimetracker,
|
||||
AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
|
||||
EnableDependencies: form.EnableIssueDependencies,
|
||||
}))
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker)
|
||||
} else {
|
||||
if !unit_model.TypeExternalTracker.UnitGlobalDisabled() {
|
||||
|
@ -613,63 +594,46 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
|
|||
}
|
||||
|
||||
if form.EnableProjects && !unit_model.TypeProjects.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeProjects,
|
||||
Config: &repo_model.ProjectsConfig{
|
||||
ProjectsMode: repo_model.ProjectsMode(form.ProjectsMode),
|
||||
},
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeProjects, &repo_model.ProjectsConfig{
|
||||
ProjectsMode: repo_model.ProjectsMode(form.ProjectsMode),
|
||||
}))
|
||||
} else if !unit_model.TypeProjects.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects)
|
||||
}
|
||||
|
||||
if form.EnableReleases && !unit_model.TypeReleases.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeReleases,
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeReleases, nil))
|
||||
} else if !unit_model.TypeReleases.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeReleases)
|
||||
}
|
||||
|
||||
if form.EnablePackages && !unit_model.TypePackages.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypePackages,
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypePackages, nil))
|
||||
} else if !unit_model.TypePackages.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePackages)
|
||||
}
|
||||
|
||||
if form.EnableActions && !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypeActions,
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypeActions, nil))
|
||||
} else if !unit_model.TypeActions.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeActions)
|
||||
}
|
||||
|
||||
if form.EnablePulls && !unit_model.TypePullRequests.UnitGlobalDisabled() {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: unit_model.TypePullRequests,
|
||||
Config: &repo_model.PullRequestsConfig{
|
||||
IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace,
|
||||
AllowMerge: form.PullsAllowMerge,
|
||||
AllowRebase: form.PullsAllowRebase,
|
||||
AllowRebaseMerge: form.PullsAllowRebaseMerge,
|
||||
AllowSquash: form.PullsAllowSquash,
|
||||
AllowFastForwardOnly: form.PullsAllowFastForwardOnly,
|
||||
AllowManualMerge: form.PullsAllowManualMerge,
|
||||
AutodetectManualMerge: form.EnableAutodetectManualMerge,
|
||||
AllowRebaseUpdate: form.PullsAllowRebaseUpdate,
|
||||
DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge,
|
||||
DefaultMergeStyle: repo_model.MergeStyle(form.PullsDefaultMergeStyle),
|
||||
DefaultAllowMaintainerEdit: form.DefaultAllowMaintainerEdit,
|
||||
},
|
||||
})
|
||||
units = append(units, newRepoUnit(repo, unit_model.TypePullRequests, &repo_model.PullRequestsConfig{
|
||||
IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace,
|
||||
AllowMerge: form.PullsAllowMerge,
|
||||
AllowRebase: form.PullsAllowRebase,
|
||||
AllowRebaseMerge: form.PullsAllowRebaseMerge,
|
||||
AllowSquash: form.PullsAllowSquash,
|
||||
AllowFastForwardOnly: form.PullsAllowFastForwardOnly,
|
||||
AllowManualMerge: form.PullsAllowManualMerge,
|
||||
AutodetectManualMerge: form.EnableAutodetectManualMerge,
|
||||
AllowRebaseUpdate: form.PullsAllowRebaseUpdate,
|
||||
DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge,
|
||||
DefaultMergeStyle: repo_model.MergeStyle(form.PullsDefaultMergeStyle),
|
||||
DefaultAllowMaintainerEdit: form.DefaultAllowMaintainerEdit,
|
||||
}))
|
||||
} else if !unit_model.TypePullRequests.UnitGlobalDisabled() {
|
||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePullRequests)
|
||||
}
|
||||
|
|
|
@ -1078,6 +1078,8 @@ func registerRoutes(m *web.Router) {
|
|||
m.Post("/avatar", web.Bind(forms.AvatarForm{}), repo_setting.SettingsAvatar)
|
||||
m.Post("/avatar/delete", repo_setting.SettingsDeleteAvatar)
|
||||
|
||||
m.Combo("/public_access").Get(repo_setting.PublicAccess).Post(repo_setting.PublicAccessPost)
|
||||
|
||||
m.Group("/collaboration", func() {
|
||||
m.Combo("").Get(repo_setting.Collaboration).Post(repo_setting.CollaborationPost)
|
||||
m.Post("/access_mode", repo_setting.ChangeCollaborationAccessMode)
|
||||
|
|
|
@ -110,17 +110,14 @@ type RepoSettingForm struct {
|
|||
EnablePrune bool
|
||||
|
||||
// Advanced settings
|
||||
EnableCode bool
|
||||
DefaultCodeEveryoneAccess string
|
||||
EnableCode bool
|
||||
|
||||
EnableWiki bool
|
||||
EnableExternalWiki bool
|
||||
DefaultWikiBranch string
|
||||
DefaultWikiEveryoneAccess string
|
||||
ExternalWikiURL string
|
||||
EnableWiki bool
|
||||
EnableExternalWiki bool
|
||||
DefaultWikiBranch string
|
||||
ExternalWikiURL string
|
||||
|
||||
EnableIssues bool
|
||||
DefaultIssuesEveryoneAccess string
|
||||
EnableExternalTracker bool
|
||||
ExternalTrackerURL string
|
||||
TrackerURLFormat string
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
<div class="repo-icon only-mobile" data-tooltip-content="{{ctx.Locale.Tr "repo.desc.internal"}}">{{svg "octicon-shield-lock" 18}}</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if $.Permission.HasAnyUnitPublicAccess}}
|
||||
<span class="ui basic orange label">{{ctx.Locale.Tr "repo.desc.public_access"}}</span>
|
||||
{{end}}
|
||||
{{if .IsTemplate}}
|
||||
<span class="ui basic label not-mobile">{{ctx.Locale.Tr "repo.desc.template"}}</span>
|
||||
<div class="repo-icon only-mobile" data-tooltip-content="{{ctx.Locale.Tr "repo.desc.template"}}">{{svg "octicon-repo-template" 18}}</div>
|
||||
|
@ -208,7 +211,7 @@
|
|||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanReadAny ctx.Consts.RepoUnitTypePullRequests ctx.Consts.RepoUnitTypeIssues ctx.Consts.RepoUnitTypeReleases) (not .IsEmptyRepo)}}
|
||||
{{if and (.Permission.CanReadAny ctx.Consts.RepoUnitTypePullRequests ctx.Consts.RepoUnitTypeIssues ctx.Consts.RepoUnitTypeReleases ctx.Consts.RepoUnitTypeCode) (not .IsEmptyRepo)}}
|
||||
<a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity">
|
||||
{{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}}
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{{$canReadCode := $.Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
|
||||
|
||||
<div class="ui fluid vertical menu">
|
||||
{{/* the default activity page "pulse" could work with any permission: code, issue, pr, release*/}}
|
||||
<a class="{{if .PageIsPulse}}active {{end}}item" href="{{.RepoLink}}/activity">
|
||||
{{ctx.Locale.Tr "repo.activity.navbar.pulse"}}
|
||||
</a>
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
<a class="{{if .PageIsSettingsOptions}}active {{end}}item" href="{{.RepoLink}}/settings">
|
||||
{{ctx.Locale.Tr "repo.settings.options"}}
|
||||
</a>
|
||||
{{if or .Repository.IsPrivate .Permission.HasAnyUnitPublicAccess}}
|
||||
<a class="{{if .PageIsSettingsPublicAccess}}active {{end}}item" href="{{.RepoLink}}/settings/public_access">
|
||||
{{ctx.Locale.Tr "repo.settings.public_access"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="{{if .PageIsSettingsCollaboration}}active {{end}}item" href="{{.RepoLink}}/settings/collaboration">
|
||||
{{ctx.Locale.Tr "repo.settings.collaboration"}}
|
||||
</a>
|
||||
|
|
|
@ -310,15 +310,6 @@
|
|||
<input class="enable-system" name="enable_code" type="checkbox"{{if $isCodeEnabled}} checked{{end}}>
|
||||
<label>{{ctx.Locale.Tr "repo.code.desc"}}</label>
|
||||
</div>
|
||||
<div class="inline field tw-pl-4">
|
||||
{{$unitCode := .Repository.MustGetUnit ctx ctx.Consts.RepoUnitTypeCode}}
|
||||
<label>{{ctx.Locale.Tr "repo.settings.default_permission_everyone_access"}}</label>
|
||||
<select name="default_code_everyone_access" class="ui selection dropdown">
|
||||
{{/* everyone access mode is different from others, none means it is unset and won't be applied */}}
|
||||
<option value="none" {{Iif (eq $unitCode.EveryoneAccessMode 0) "selected"}}>{{ctx.Locale.Tr "settings.permission_not_set"}}</option>
|
||||
<option value="read" {{Iif (eq $unitCode.EveryoneAccessMode 1) "selected"}}>{{ctx.Locale.Tr "settings.permission_read"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{$isInternalWikiEnabled := .Repository.UnitEnabled ctx ctx.Consts.RepoUnitTypeWiki}}
|
||||
|
@ -346,16 +337,6 @@
|
|||
<label>{{ctx.Locale.Tr "repo.settings.default_wiki_branch_name"}}</label>
|
||||
<input name="default_wiki_branch" value="{{.Repository.DefaultWikiBranch}}">
|
||||
</div>
|
||||
<div class="inline field">
|
||||
{{$unitInternalWiki := .Repository.MustGetUnit ctx ctx.Consts.RepoUnitTypeWiki}}
|
||||
<label>{{ctx.Locale.Tr "repo.settings.default_permission_everyone_access"}}</label>
|
||||
<select name="default_wiki_everyone_access" class="ui selection dropdown">
|
||||
{{/* everyone access mode is different from others, none means it is unset and won't be applied */}}
|
||||
<option value="none" {{Iif (eq $unitInternalWiki.EveryoneAccessMode 0) "selected"}}>{{ctx.Locale.Tr "settings.permission_not_set"}}</option>
|
||||
<option value="read" {{Iif (eq $unitInternalWiki.EveryoneAccessMode 1) "selected"}}>{{ctx.Locale.Tr "settings.permission_read"}}</option>
|
||||
<option value="write" {{Iif (eq $unitInternalWiki.EveryoneAccessMode 2) "selected"}}>{{ctx.Locale.Tr "settings.permission_write"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
|
||||
|
@ -391,15 +372,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="field tw-pl-4 {{if (.Repository.UnitEnabled ctx ctx.Consts.RepoUnitTypeExternalTracker)}}disabled{{end}}" id="internal_issue_box">
|
||||
<div class="inline field">
|
||||
{{$unitIssue := .Repository.MustGetUnit ctx ctx.Consts.RepoUnitTypeIssues}}
|
||||
<label>{{ctx.Locale.Tr "repo.settings.default_permission_everyone_access"}}</label>
|
||||
<select name="default_issues_everyone_access" class="ui selection dropdown">
|
||||
{{/* everyone access mode is different from others, none means it is unset and won't be applied */}}
|
||||
<option value="none" {{Iif (eq $unitIssue.EveryoneAccessMode 0) "selected"}}>{{ctx.Locale.Tr "settings.permission_not_set"}}</option>
|
||||
<option value="read" {{Iif (eq $unitIssue.EveryoneAccessMode 1) "selected"}}>{{ctx.Locale.Tr "settings.permission_read"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
{{if .Repository.CanEnableTimetracker}}
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
{{template "repo/settings/layout_head" (dict "ctxData" . "pageClass" "repository settings")}}
|
||||
<div class="repo-setting-content">
|
||||
{{$paNotSet := "not-set"}}
|
||||
{{$paAnonymousRead := "anonymous-read"}}
|
||||
{{$paEveryoneRead := "everyone-read"}}
|
||||
{{$paEveryoneWrite := "everyone-write"}}
|
||||
<form class="ui form" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<table class="ui table unstackable tw-my-2">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ctx.Locale.Tr "settings.permission_not_set"}}</th>
|
||||
<th>{{ctx.Locale.Tr "settings.permission_anonymous_read"}}</th>
|
||||
<th>{{ctx.Locale.Tr "settings.permission_everyone_read"}}</th>
|
||||
<th>{{ctx.Locale.Tr "settings.permission_everyone_write"}}</th>
|
||||
</tr>
|
||||
{{range $ua := .RepoUnitPublicAccesses}}
|
||||
<tr>
|
||||
<td>{{$ua.DisplayName}}</td>
|
||||
<td class="tw-text-center"><label><input type="radio" name="{{$ua.FormKey}}" value="{{$paNotSet}}" {{Iif (eq $paNotSet $ua.UnitPublicAccess) "checked"}}></label></td>
|
||||
<td class="tw-text-center"><label><input type="radio" name="{{$ua.FormKey}}" value="{{$paAnonymousRead}}" {{Iif (eq $paAnonymousRead $ua.UnitPublicAccess) "checked"}}></label></td>
|
||||
<td class="tw-text-center"><label><input type="radio" name="{{$ua.FormKey}}" value="{{$paEveryoneRead}}" {{Iif (eq $paEveryoneRead $ua.UnitPublicAccess) "checked"}}></label></td>
|
||||
<td class="tw-text-center">
|
||||
{{if SliceUtils.Contains $ua.PublicAccessTypes $paEveryoneWrite}}
|
||||
<label><input type="radio" name="{{$ua.FormKey}}" value="{{$paEveryoneWrite}}" {{Iif (eq $paEveryoneWrite $ua.UnitPublicAccess) "checked"}}></label>
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
<button class="ui primary button {{if .GlobalForcePrivate}}disabled{{end}}">{{ctx.Locale.Tr "repo.settings.update_settings"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
{{template "repo/settings/layout_footer" .}}
|
|
@ -7,10 +7,12 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
@ -19,8 +21,26 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestViewRepo(t *testing.T) {
|
||||
func TestRepoView(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
t.Run("ViewRepoPublic", testViewRepoPublic)
|
||||
t.Run("ViewRepoWithCache", testViewRepoWithCache)
|
||||
t.Run("ViewRepoPrivate", testViewRepoPrivate)
|
||||
t.Run("ViewRepo1CloneLinkAnonymous", testViewRepo1CloneLinkAnonymous)
|
||||
t.Run("ViewRepo1CloneLinkAuthorized", testViewRepo1CloneLinkAuthorized)
|
||||
t.Run("ViewRepoWithSymlinks", testViewRepoWithSymlinks)
|
||||
t.Run("ViewFileInRepo", testViewFileInRepo)
|
||||
t.Run("BlameFileInRepo", testBlameFileInRepo)
|
||||
t.Run("ViewRepoDirectory", testViewRepoDirectory)
|
||||
t.Run("ViewRepoDirectoryReadme", testViewRepoDirectoryReadme)
|
||||
t.Run("MarkDownReadmeImage", testMarkDownReadmeImage)
|
||||
t.Run("MarkDownReadmeImageSubfolder", testMarkDownReadmeImageSubfolder)
|
||||
t.Run("GeneratedSourceLink", testGeneratedSourceLink)
|
||||
t.Run("ViewCommit", testViewCommit)
|
||||
}
|
||||
|
||||
func testViewRepoPublic(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -41,87 +61,118 @@ func TestViewRepo(t *testing.T) {
|
|||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func testViewRepo(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepoWithCache(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
testView := func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/org3/repo3")
|
||||
session := loginUser(t, "user2")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req := NewRequest(t, "GET", "/org3/repo3")
|
||||
session := loginUser(t, "user2")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
files := htmlDoc.doc.Find("#repo-files-table .repo-file-item")
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
files := htmlDoc.doc.Find("#repo-files-table .repo-file-item")
|
||||
type file struct {
|
||||
fileName string
|
||||
commitID string
|
||||
commitMsg string
|
||||
commitTime string
|
||||
}
|
||||
|
||||
type file struct {
|
||||
fileName string
|
||||
commitID string
|
||||
commitMsg string
|
||||
commitTime string
|
||||
}
|
||||
var items []file
|
||||
|
||||
var items []file
|
||||
files.Each(func(i int, s *goquery.Selection) {
|
||||
tds := s.Find(".repo-file-cell")
|
||||
var f file
|
||||
tds.Each(func(i int, s *goquery.Selection) {
|
||||
if i == 0 {
|
||||
f.fileName = strings.TrimSpace(s.Text())
|
||||
} else if i == 1 {
|
||||
a := s.Find("a")
|
||||
f.commitMsg = strings.TrimSpace(a.Text())
|
||||
l, _ := a.Attr("href")
|
||||
f.commitID = path.Base(l)
|
||||
}
|
||||
})
|
||||
|
||||
files.Each(func(i int, s *goquery.Selection) {
|
||||
tds := s.Find(".repo-file-cell")
|
||||
var f file
|
||||
tds.Each(func(i int, s *goquery.Selection) {
|
||||
if i == 0 {
|
||||
f.fileName = strings.TrimSpace(s.Text())
|
||||
} else if i == 1 {
|
||||
a := s.Find("a")
|
||||
f.commitMsg = strings.TrimSpace(a.Text())
|
||||
l, _ := a.Attr("href")
|
||||
f.commitID = path.Base(l)
|
||||
}
|
||||
// convert "2017-06-14 21:54:21 +0800" to "Wed, 14 Jun 2017 13:54:21 UTC"
|
||||
htmlTimeString, _ := s.Find("relative-time").Attr("datetime")
|
||||
htmlTime, _ := time.Parse(time.RFC3339, htmlTimeString)
|
||||
f.commitTime = htmlTime.In(time.Local).Format(time.RFC1123)
|
||||
items = append(items, f)
|
||||
})
|
||||
|
||||
// convert "2017-06-14 21:54:21 +0800" to "Wed, 14 Jun 2017 13:54:21 UTC"
|
||||
htmlTimeString, _ := s.Find("relative-time").Attr("datetime")
|
||||
htmlTime, _ := time.Parse(time.RFC3339, htmlTimeString)
|
||||
f.commitTime = htmlTime.In(time.Local).Format(time.RFC1123)
|
||||
items = append(items, f)
|
||||
})
|
||||
commitT := time.Date(2017, time.June, 14, 13, 54, 21, 0, time.UTC).In(time.Local).Format(time.RFC1123)
|
||||
assert.EqualValues(t, []file{
|
||||
{
|
||||
fileName: "doc",
|
||||
commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
|
||||
commitMsg: "init project",
|
||||
commitTime: commitT,
|
||||
},
|
||||
{
|
||||
fileName: "README.md",
|
||||
commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
|
||||
commitMsg: "init project",
|
||||
commitTime: commitT,
|
||||
},
|
||||
}, items)
|
||||
}
|
||||
|
||||
commitT := time.Date(2017, time.June, 14, 13, 54, 21, 0, time.UTC).In(time.Local).Format(time.RFC1123)
|
||||
assert.EqualValues(t, []file{
|
||||
{
|
||||
fileName: "doc",
|
||||
commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
|
||||
commitMsg: "init project",
|
||||
commitTime: commitT,
|
||||
},
|
||||
{
|
||||
fileName: "README.md",
|
||||
commitID: "2a47ca4b614a9f5a43abbd5ad851a54a616ffee6",
|
||||
commitMsg: "init project",
|
||||
commitTime: commitT,
|
||||
},
|
||||
}, items)
|
||||
}
|
||||
|
||||
func TestViewRepo2(t *testing.T) {
|
||||
// FIXME: these test don't seem quite right, no enough assert
|
||||
// no last commit cache
|
||||
testViewRepo(t)
|
||||
|
||||
testView(t)
|
||||
// enable last commit cache for all repositories
|
||||
oldCommitsCount := setting.CacheService.LastCommit.CommitsCount
|
||||
setting.CacheService.LastCommit.CommitsCount = 0
|
||||
// first view will not hit the cache
|
||||
testViewRepo(t)
|
||||
testView(t)
|
||||
// second view will hit the cache
|
||||
testViewRepo(t)
|
||||
testView(t)
|
||||
setting.CacheService.LastCommit.CommitsCount = oldCommitsCount
|
||||
}
|
||||
|
||||
func TestViewRepo3(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepoPrivate(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/org3/repo3")
|
||||
session := loginUser(t, "user4")
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
t.Run("OrgMemberAccess", func(t *testing.T) {
|
||||
req = NewRequest(t, "GET", "/org3/repo3")
|
||||
session := loginUser(t, "user4")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), `<div id="repo-files-table"`)
|
||||
})
|
||||
|
||||
t.Run("PublicAccess-AnonymousAccess", func(t *testing.T) {
|
||||
session := loginUser(t, "user1")
|
||||
|
||||
// set unit code to "anonymous read"
|
||||
req = NewRequestWithValues(t, "POST", "/org3/repo3/settings/public_access", map[string]string{
|
||||
"_csrf": GetUserCSRFToken(t, session),
|
||||
"repo-unit-access-" + strconv.Itoa(int(unit.TypeCode)): "anonymous-read",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// try to "anonymous read" (ok)
|
||||
req = NewRequest(t, "GET", "/org3/repo3")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), `<span class="ui basic orange label">Public Access</span>`)
|
||||
|
||||
// remove "anonymous read"
|
||||
req = NewRequestWithValues(t, "POST", "/org3/repo3/settings/public_access", map[string]string{
|
||||
"_csrf": GetUserCSRFToken(t, session),
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// try to "anonymous read" (not found)
|
||||
req = NewRequest(t, "GET", "/org3/repo3")
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
|
||||
func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepo1CloneLinkAnonymous(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/user2/repo1")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
@ -139,8 +190,8 @@ func TestViewRepo1CloneLinkAnonymous(t *testing.T) {
|
|||
assert.Equal(t, "tea clone user2/repo1", link)
|
||||
}
|
||||
|
||||
func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepo1CloneLinkAuthorized(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -162,8 +213,8 @@ func TestViewRepo1CloneLinkAuthorized(t *testing.T) {
|
|||
assert.Equal(t, "tea clone user2/repo1", link)
|
||||
}
|
||||
|
||||
func TestViewRepoWithSymlinks(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepoWithSymlinks(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
defer test.MockVariableValue(&setting.UI.FileIconTheme, "basic")()
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -186,8 +237,8 @@ func TestViewRepoWithSymlinks(t *testing.T) {
|
|||
}
|
||||
|
||||
// TestViewFileInRepo repo description, topics and summary should not be displayed when viewing a file
|
||||
func TestViewFileInRepo(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewFileInRepo(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -205,8 +256,8 @@ func TestViewFileInRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
// TestBlameFileInRepo repo description, topics and summary should not be displayed when running blame on a file
|
||||
func TestBlameFileInRepo(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testBlameFileInRepo(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -224,8 +275,8 @@ func TestBlameFileInRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
// TestViewRepoDirectory repo description, topics and summary should not be displayed when within a directory
|
||||
func TestViewRepoDirectory(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepoDirectory(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -246,8 +297,8 @@ func TestViewRepoDirectory(t *testing.T) {
|
|||
}
|
||||
|
||||
// ensure that the all the different ways to find and render a README work
|
||||
func TestViewRepoDirectoryReadme(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewRepoDirectoryReadme(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// there are many combinations:
|
||||
// - READMEs can be .md, .txt, or have no extension
|
||||
|
@ -353,8 +404,8 @@ func TestViewRepoDirectoryReadme(t *testing.T) {
|
|||
missing("symlink-loop", "/user2/readme-test/src/branch/symlink-loop/")
|
||||
}
|
||||
|
||||
func TestMarkDownReadmeImage(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testMarkDownReadmeImage(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -375,8 +426,8 @@ func TestMarkDownReadmeImage(t *testing.T) {
|
|||
assert.Equal(t, "/user2/repo1/media/branch/home-md-img-check/test-fake-img.jpg", src)
|
||||
}
|
||||
|
||||
func TestMarkDownReadmeImageSubfolder(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testMarkDownReadmeImageSubfolder(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
|
@ -398,8 +449,8 @@ func TestMarkDownReadmeImageSubfolder(t *testing.T) {
|
|||
assert.Equal(t, "/user2/repo1/media/branch/sub-home-md-img-check/docs/test-fake-img.jpg", src)
|
||||
}
|
||||
|
||||
func TestGeneratedSourceLink(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testGeneratedSourceLink(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("Rendered file", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
@ -434,8 +485,8 @@ func TestGeneratedSourceLink(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestViewCommit(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
func testViewCommit(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/user2/repo1/commit/0123456789012345678901234567890123456789")
|
||||
req.Header.Add("Accept", "text/html")
|
||||
|
|
Loading…
Reference in New Issue