aboutsummaryrefslogtreecommitdiffstats
path: root/modules/context/context_model.go
blob: 5ba98f7e01a50bff20fb7195d93b54a953153771 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package context

import (
	"path"
	"strings"

	"code.gitea.io/gitea/models/unit"
	"code.gitea.io/gitea/modules/git"
	"code.gitea.io/gitea/modules/issue/template"
	"code.gitea.io/gitea/modules/log"
	api "code.gitea.io/gitea/modules/structs"
)

// IsUserSiteAdmin returns true if current user is a site admin
func (ctx *Context) IsUserSiteAdmin() bool {
	return ctx.IsSigned && ctx.Doer.IsAdmin
}

// IsUserRepoOwner returns true if current user owns current repo
func (ctx *Context) IsUserRepoOwner() bool {
	return ctx.Repo.IsOwner()
}

// IsUserRepoAdmin returns true if current user is admin in current repo
func (ctx *Context) IsUserRepoAdmin() bool {
	return ctx.Repo.IsAdmin()
}

// IsUserRepoWriter returns true if current user has write privilege in current repo
func (ctx *Context) IsUserRepoWriter(unitTypes []unit.Type) bool {
	for _, unitType := range unitTypes {
		if ctx.Repo.CanWrite(unitType) {
			return true
		}
	}

	return false
}

// IsUserRepoReaderSpecific returns true if current user can read current repo's specific part
func (ctx *Context) IsUserRepoReaderSpecific(unitType unit.Type) bool {
	return ctx.Repo.CanRead(unitType)
}

// IsUserRepoReaderAny returns true if current user can read any part of current repo
func (ctx *Context) IsUserRepoReaderAny() bool {
	return ctx.Repo.HasAccess()
}

// IssueTemplatesFromDefaultBranch checks for valid issue templates in the repo's default branch,
func (ctx *Context) IssueTemplatesFromDefaultBranch() []*api.IssueTemplate {
	ret, _ := ctx.IssueTemplatesErrorsFromDefaultBranch()
	return ret
}

// IssueTemplatesErrorsFromDefaultBranch checks for issue templates in the repo's default branch,
// returns valid templates and the errors of invalid template files.
func (ctx *Context) IssueTemplatesErrorsFromDefaultBranch() ([]*api.IssueTemplate, map[string]error) {
	var issueTemplates []*api.IssueTemplate

	if ctx.Repo.Repository.IsEmpty {
		return issueTemplates, nil
	}

	if ctx.Repo.Commit == nil {
		var err error
		ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
		if err != nil {
			return issueTemplates, nil
		}
	}

	invalidFiles := map[string]error{}
	for _, dirName := range IssueTemplateDirCandidates {
		tree, err := ctx.Repo.Commit.SubTree(dirName)
		if err != nil {
			log.Debug("get sub tree of %s: %v", dirName, err)
			continue
		}
		entries, err := tree.ListEntries()
		if err != nil {
			log.Debug("list entries in %s: %v", dirName, err)
			return issueTemplates, nil
		}
		for _, entry := range entries {
			if !template.CouldBe(entry.Name()) {
				continue
			}
			fullName := path.Join(dirName, entry.Name())
			if it, err := template.UnmarshalFromEntry(entry, dirName); err != nil {
				invalidFiles[fullName] = err
			} else {
				if !strings.HasPrefix(it.Ref, "refs/") { // Assume that the ref intended is always a branch - for tags users should use refs/tags/<ref>
					it.Ref = git.BranchPrefix + it.Ref
				}
				issueTemplates = append(issueTemplates, it)
			}
		}
	}
	return issueTemplates, invalidFiles
}

// IssueConfigFromDefaultBranch returns the issue config for this repo.
// It never returns a nil config.
func (ctx *Context) IssueConfigFromDefaultBranch() (api.IssueConfig, error) {
	if ctx.Repo.Repository.IsEmpty {
		return GetDefaultIssueConfig(), nil
	}

	commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
	if err != nil {
		return GetDefaultIssueConfig(), err
	}

	for _, configName := range IssueConfigCandidates {
		if _, err := commit.GetTreeEntryByPath(configName + ".yaml"); err == nil {
			return ctx.Repo.GetIssueConfig(configName+".yaml", commit)
		}

		if _, err := commit.GetTreeEntryByPath(configName + ".yml"); err == nil {
			return ctx.Repo.GetIssueConfig(configName+".yml", commit)
		}
	}

	return GetDefaultIssueConfig(), nil
}

func (ctx *Context) HasIssueTemplatesOrContactLinks() bool {
	if len(ctx.IssueTemplatesFromDefaultBranch()) > 0 {
		return true
	}

	issueConfig, _ := ctx.IssueConfigFromDefaultBranch()
	return len(issueConfig.ContactLinks) > 0
}