Skip to content

Commit 342c480

Browse files
committed
fix
1 parent 040970c commit 342c480

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+660
-664
lines changed

modules/context/api.go

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,31 @@ import (
1313

1414
"code.gitea.io/gitea/models/auth"
1515
repo_model "code.gitea.io/gitea/models/repo"
16-
"code.gitea.io/gitea/modules/cache"
16+
"code.gitea.io/gitea/models/unit"
17+
user_model "code.gitea.io/gitea/models/user"
18+
mc "code.gitea.io/gitea/modules/cache"
1719
"code.gitea.io/gitea/modules/git"
1820
"code.gitea.io/gitea/modules/httpcache"
1921
"code.gitea.io/gitea/modules/log"
2022
"code.gitea.io/gitea/modules/setting"
21-
"code.gitea.io/gitea/modules/web/middleware"
23+
24+
"gitea.com/go-chi/cache"
2225
)
2326

2427
// APIContext is a specific context for API service
2528
type APIContext struct {
26-
*Context
27-
Org *APIOrganization
29+
*Base
30+
31+
Cache cache.Cache
32+
33+
Doer *user_model.User
34+
IsSigned bool
35+
IsBasicAuth bool
36+
37+
ContextUser *user_model.User
38+
Repo *Repository
39+
Org *APIOrganization
40+
Package *Package
2841
}
2942

3043
// Currently, we have the following common fields in error response:
@@ -128,11 +141,6 @@ type apiContextKeyType struct{}
128141

129142
var apiContextKey = apiContextKeyType{}
130143

131-
// WithAPIContext set up api context in request
132-
func WithAPIContext(req *http.Request, ctx *APIContext) *http.Request {
133-
return req.WithContext(context.WithValue(req.Context(), apiContextKey, ctx))
134-
}
135-
136144
// GetAPIContext returns a context for API routes
137145
func GetAPIContext(req *http.Request) *APIContext {
138146
return req.Context().Value(apiContextKey).(*APIContext)
@@ -195,21 +203,21 @@ func (ctx *APIContext) CheckForOTP() {
195203
}
196204

197205
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
198-
twofa, err := auth.GetTwoFactorByUID(ctx.Context.Doer.ID)
206+
twofa, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
199207
if err != nil {
200208
if auth.IsErrTwoFactorNotEnrolled(err) {
201209
return // No 2FA enrollment for this user
202210
}
203-
ctx.Context.Error(http.StatusInternalServerError)
211+
ctx.Error(http.StatusInternalServerError, "GetTwoFactorByUID", err)
204212
return
205213
}
206214
ok, err := twofa.ValidateTOTP(otpHeader)
207215
if err != nil {
208-
ctx.Context.Error(http.StatusInternalServerError)
216+
ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err)
209217
return
210218
}
211219
if !ok {
212-
ctx.Context.Error(http.StatusUnauthorized)
220+
ctx.Error(http.StatusUnauthorized, "", nil)
213221
return
214222
}
215223
}
@@ -218,23 +226,17 @@ func (ctx *APIContext) CheckForOTP() {
218226
func APIContexter() func(http.Handler) http.Handler {
219227
return func(next http.Handler) http.Handler {
220228
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
221-
locale := middleware.Locale(w, req)
222-
ctx := APIContext{
223-
Context: &Context{
224-
Resp: NewResponse(w),
225-
Data: middleware.GetContextData(req.Context()),
226-
Locale: locale,
227-
Cache: cache.GetCache(),
228-
Repo: &Repository{
229-
PullRequest: &PullRequest{},
230-
},
231-
Org: &Organization{},
232-
},
233-
Org: &APIOrganization{},
229+
base, baseCleanUp := NewBaseContext(w, req)
230+
ctx := &APIContext{
231+
Base: base,
232+
Cache: mc.GetCache(),
233+
Repo: &Repository{PullRequest: &PullRequest{}},
234+
Org: &APIOrganization{},
234235
}
235-
defer ctx.Close()
236+
defer baseCleanUp()
236237

237-
ctx.Req = WithAPIContext(WithContext(req, ctx.Context), &ctx)
238+
ctx.Base.AppendContextValue(apiContextKey, ctx)
239+
ctx.Base.AppendContextValueFunc(git.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
238240

239241
// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
240242
if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
@@ -247,8 +249,6 @@ func APIContexter() func(http.Handler) http.Handler {
247249
httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform")
248250
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
249251

250-
ctx.Data["Context"] = &ctx
251-
252252
next.ServeHTTP(ctx.Resp, ctx.Req)
253253
})
254254
}
@@ -301,7 +301,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
301301
return func() {
302302
// If it's been set to nil then assume someone else has closed it.
303303
if ctx.Repo.GitRepo != nil {
304-
ctx.Repo.GitRepo.Close()
304+
_ = ctx.Repo.GitRepo.Close()
305305
}
306306
}
307307
}
@@ -337,7 +337,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
337337
}
338338

339339
var err error
340-
refName := getRefName(ctx.Context, RepoRefAny)
340+
refName := getRefName(ctx.Base, ctx.Repo, RepoRefAny)
341341

342342
if ctx.Repo.GitRepo.IsBranchExist(refName) {
343343
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
@@ -368,3 +368,44 @@ func RepoRefForAPI(next http.Handler) http.Handler {
368368
next.ServeHTTP(w, req)
369369
})
370370
}
371+
372+
// HasAPIError returns true if error occurs in form validation.
373+
func (ctx *APIContext) HasAPIError() bool {
374+
hasErr, ok := ctx.Data["HasError"]
375+
if !ok {
376+
return false
377+
}
378+
return hasErr.(bool)
379+
}
380+
381+
// NotFoundOrServerError use error check function to determine if the error
382+
// is about not found. It responds with 404 status code for not found error,
383+
// or error context description for logging purpose of 500 server error.
384+
func (ctx *APIContext) NotFoundOrServerError(logMsg string, errCheck func(error) bool, logErr error) {
385+
if errCheck(logErr) {
386+
ctx.JSON(http.StatusNotFound, nil)
387+
return
388+
}
389+
ctx.Error(http.StatusInternalServerError, "NotFoundOrServerError", logMsg)
390+
}
391+
392+
// IsUserSiteAdmin returns true if current user is a site admin
393+
func (ctx *APIContext) IsUserSiteAdmin() bool {
394+
return ctx.IsSigned && ctx.Doer.IsAdmin
395+
}
396+
397+
// IsUserRepoAdmin returns true if current user is admin in current repo
398+
func (ctx *APIContext) IsUserRepoAdmin() bool {
399+
return ctx.Repo.IsAdmin()
400+
}
401+
402+
// IsUserRepoWriter returns true if current user has write privilege in current repo
403+
func (ctx *APIContext) IsUserRepoWriter(unitTypes []unit.Type) bool {
404+
for _, unitType := range unitTypes {
405+
if ctx.Repo.CanWrite(unitType) {
406+
return true
407+
}
408+
}
409+
410+
return false
411+
}

0 commit comments

Comments
 (0)