Skip to content

Commit b9e852e

Browse files
committed
Some improvements
1 parent 8ddf817 commit b9e852e

File tree

1 file changed

+61
-57
lines changed

1 file changed

+61
-57
lines changed

routers/api/v1/api.go

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -235,54 +235,6 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
235235
}
236236
}
237237

238-
// if a token is being used for auth, we check that it contains the required scope
239-
// if a token is not being used, reqToken will enforce other sign in methods
240-
func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeCategory) func(ctx *context.APIContext) {
241-
return func(ctx *context.APIContext) {
242-
// no scope required
243-
if len(requiredScopeCategories) == 0 {
244-
return
245-
}
246-
247-
// Need OAuth2 token to be present.
248-
scope, scopeExists := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
249-
if ctx.Data["IsApiToken"] != true || !scopeExists {
250-
return
251-
}
252-
253-
// use the http method to determine the access level
254-
requiredScopeLevel := auth_model.Read
255-
if ctx.Req.Method == "POST" || ctx.Req.Method == "PUT" || ctx.Req.Method == "PATCH" || ctx.Req.Method == "DELETE" {
256-
requiredScopeLevel = auth_model.Write
257-
}
258-
259-
// get the required scope for the given access level and category
260-
requiredScopes := auth_model.GetRequiredScopes(requiredScopeLevel, requiredScopeCategories...)
261-
allow, err := scope.HasScope(requiredScopes...)
262-
if err != nil {
263-
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
264-
return
265-
}
266-
267-
if !allow {
268-
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s): %v", requiredScopes))
269-
return
270-
}
271-
272-
ctx.Data["requiredScopeCategories"] = requiredScopeCategories
273-
274-
// check if scope only applies to public resources
275-
publicOnly, err := scope.PublicOnly()
276-
if err != nil {
277-
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "parsing public resource scope failed: "+err.Error())
278-
return
279-
}
280-
281-
// assign to true so that those searching should only filter public repositories/users/organizations
282-
ctx.PublicOnly = publicOnly
283-
}
284-
}
285-
286238
func checkTokenPublicOnly() func(ctx *context.APIContext) {
287239
return func(ctx *context.APIContext) {
288240
if !ctx.PublicOnly {
@@ -296,12 +248,16 @@ func checkTokenPublicOnly() func(ctx *context.APIContext) {
296248

297249
// public Only permission check
298250
switch {
299-
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository),
300-
auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryIssue):
251+
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository):
301252
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
302253
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public repos")
303254
return
304255
}
256+
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryIssue):
257+
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
258+
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public issues")
259+
return
260+
}
305261
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryOrganization):
306262
if ctx.Org.Organization != nil && ctx.Org.Organization.Visibility != api.VisibleTypePublic {
307263
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
@@ -335,6 +291,54 @@ func checkTokenPublicOnly() func(ctx *context.APIContext) {
335291
}
336292
}
337293

294+
// if a token is being used for auth, we check that it contains the required scope
295+
// if a token is not being used, reqToken will enforce other sign in methods
296+
func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeCategory) func(ctx *context.APIContext) {
297+
return func(ctx *context.APIContext) {
298+
// no scope required
299+
if len(requiredScopeCategories) == 0 {
300+
return
301+
}
302+
303+
// Need OAuth2 token to be present.
304+
scope, scopeExists := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
305+
if ctx.Data["IsApiToken"] != true || !scopeExists {
306+
return
307+
}
308+
309+
// use the http method to determine the access level
310+
requiredScopeLevel := auth_model.Read
311+
if ctx.Req.Method == "POST" || ctx.Req.Method == "PUT" || ctx.Req.Method == "PATCH" || ctx.Req.Method == "DELETE" {
312+
requiredScopeLevel = auth_model.Write
313+
}
314+
315+
// get the required scope for the given access level and category
316+
requiredScopes := auth_model.GetRequiredScopes(requiredScopeLevel, requiredScopeCategories...)
317+
allow, err := scope.HasScope(requiredScopes...)
318+
if err != nil {
319+
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
320+
return
321+
}
322+
323+
if !allow {
324+
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s): %v", requiredScopes))
325+
return
326+
}
327+
328+
ctx.Data["requiredScopeCategories"] = requiredScopeCategories
329+
330+
// check if scope only applies to public resources
331+
publicOnly, err := scope.PublicOnly()
332+
if err != nil {
333+
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "parsing public resource scope failed: "+err.Error())
334+
return
335+
}
336+
337+
// assign to true so that those searching should only filter public repositories/users/organizations
338+
ctx.PublicOnly = publicOnly
339+
}
340+
}
341+
338342
// Contexter middleware already checks token for user sign in process.
339343
func reqToken() func(ctx *context.APIContext) {
340344
return func(ctx *context.APIContext) {
@@ -941,17 +945,17 @@ func Routes() *web.Router {
941945
// Notifications (requires 'notifications' scope)
942946
m.Group("/notifications", func() {
943947
m.Combo("").
944-
Get(notify.ListNotifications).
945-
Put(notify.ReadNotifications)
946-
m.Get("/new", notify.NewAvailable)
948+
Get(reqToken(), notify.ListNotifications).
949+
Put(reqToken(), notify.ReadNotifications)
950+
m.Get("/new", reqToken(), notify.NewAvailable)
947951
m.Combo("/threads/{id}").
948-
Get(notify.GetThread).
949-
Patch(notify.ReadThread)
950-
}, reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification))
952+
Get(reqToken(), notify.GetThread).
953+
Patch(reqToken(), notify.ReadThread)
954+
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification))
951955

952956
// Users (requires user scope)
953957
m.Group("/users", func() {
954-
m.Get("/search", reqExploreSignIn(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), user.Search)
958+
m.Get("/search", reqExploreSignIn(), user.Search)
955959

956960
m.Group("/{username}", func() {
957961
m.Get("", reqExploreSignIn(), user.GetInfo)

0 commit comments

Comments
 (0)