@@ -274,6 +274,62 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
274274 }
275275}
276276
277+ func checkTokenPublicOnly () func (ctx * context.APIContext ) {
278+ return func (ctx * context.APIContext ) {
279+ if ! ctx .PublicOnly {
280+ return
281+ }
282+
283+ requiredScopeCategories , ok := ctx .Data ["requiredScopeCategories" ].([]auth_model.AccessTokenScopeCategory )
284+ if ! ok || len (requiredScopeCategories ) == 0 {
285+ return
286+ }
287+
288+ // public Only permission check
289+ switch {
290+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryRepository ):
291+ if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
292+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public repos" )
293+ return
294+ }
295+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryIssue ):
296+ if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
297+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public issues" )
298+ return
299+ }
300+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryOrganization ):
301+ if ctx .Org .Organization != nil && ctx .Org .Organization .Visibility != api .VisibleTypePublic {
302+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public orgs" )
303+ return
304+ }
305+ if ctx .ContextUser != nil && ctx .ContextUser .IsOrganization () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
306+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public orgs" )
307+ return
308+ }
309+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryUser ):
310+ if ctx .ContextUser != nil && ctx .ContextUser .IsUser () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
311+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public users" )
312+ return
313+ }
314+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryActivityPub ):
315+ if ctx .ContextUser != nil && ctx .ContextUser .IsUser () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
316+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public activitypub" )
317+ return
318+ }
319+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryNotification ):
320+ if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
321+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public notifications" )
322+ return
323+ }
324+ case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryPackage ):
325+ if ctx .Package != nil && ctx .Package .Owner .Visibility .IsPrivate () {
326+ ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public packages" )
327+ return
328+ }
329+ }
330+ }
331+ }
332+
277333// if a token is being used for auth, we check that it contains the required scope
278334// if a token is not being used, reqToken will enforce other sign in methods
279335func tokenRequiresScopes (requiredScopeCategories ... auth_model.AccessTokenScopeCategory ) func (ctx * context.APIContext ) {
@@ -289,9 +345,6 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
289345 return
290346 }
291347
292- ctx .Data ["ApiTokenScopePublicRepoOnly" ] = false
293- ctx .Data ["ApiTokenScopePublicOrgOnly" ] = false
294-
295348 // use the http method to determine the access level
296349 requiredScopeLevel := auth_model .Read
297350 if ctx .Req .Method == "POST" || ctx .Req .Method == "PUT" || ctx .Req .Method == "PATCH" || ctx .Req .Method == "DELETE" {
@@ -300,29 +353,28 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
300353
301354 // get the required scope for the given access level and category
302355 requiredScopes := auth_model .GetRequiredScopes (requiredScopeLevel , requiredScopeCategories ... )
303-
304- // check if scope only applies to public resources
305- publicOnly , err := scope .PublicOnly ()
356+ allow , err := scope .HasScope (requiredScopes ... )
306357 if err != nil {
307- ctx .Error (http .StatusForbidden , "tokenRequiresScope" , "parsing public resource scope failed: " + err .Error ())
358+ ctx .Error (http .StatusForbidden , "tokenRequiresScope" , "checking scope failed: " + err .Error ())
308359 return
309360 }
310361
311- // this context is used by the middleware in the specific route
312- ctx .Data ["ApiTokenScopePublicRepoOnly" ] = publicOnly && auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryRepository )
313- ctx .Data ["ApiTokenScopePublicOrgOnly" ] = publicOnly && auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryOrganization )
314-
315- allow , err := scope .HasScope (requiredScopes ... )
316- if err != nil {
317- ctx .Error (http .StatusForbidden , "tokenRequiresScope" , "checking scope failed: " + err .Error ())
362+ if ! allow {
363+ ctx .Error (http .StatusForbidden , "tokenRequiresScope" , fmt .Sprintf ("token does not have at least one of required scope(s): %v" , requiredScopes ))
318364 return
319365 }
320366
321- if allow {
367+ ctx .Data ["requiredScopeCategories" ] = requiredScopeCategories
368+
369+ // check if scope only applies to public resources
370+ publicOnly , err := scope .PublicOnly ()
371+ if err != nil {
372+ ctx .Error (http .StatusForbidden , "tokenRequiresScope" , "parsing public resource scope failed: " + err .Error ())
322373 return
323374 }
324375
325- ctx .Error (http .StatusForbidden , "tokenRequiresScope" , fmt .Sprintf ("token does not have at least one of required scope(s): %v" , requiredScopes ))
376+ // assign to true so that those searching should only filter public repositories/users/organizations
377+ ctx .PublicOnly = publicOnly
326378 }
327379}
328380
@@ -334,25 +386,6 @@ func reqToken() func(ctx *context.APIContext) {
334386 return
335387 }
336388
337- if true == ctx .Data ["IsApiToken" ] {
338- publicRepo , pubRepoExists := ctx .Data ["ApiTokenScopePublicRepoOnly" ]
339- publicOrg , pubOrgExists := ctx .Data ["ApiTokenScopePublicOrgOnly" ]
340-
341- if pubRepoExists && publicRepo .(bool ) &&
342- ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
343- ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public repos" )
344- return
345- }
346-
347- if pubOrgExists && publicOrg .(bool ) &&
348- ctx .Org .Organization != nil && ctx .Org .Organization .Visibility != api .VisibleTypePublic {
349- ctx .Error (http .StatusForbidden , "reqToken" , "token scope is limited to public orgs" )
350- return
351- }
352-
353- return
354- }
355-
356389 if ctx .IsSigned {
357390 return
358391 }
@@ -800,11 +833,11 @@ func Routes() *web.Route {
800833 m .Group ("/user/{username}" , func () {
801834 m .Get ("" , activitypub .Person )
802835 m .Post ("/inbox" , activitypub .ReqHTTPSignature (), activitypub .PersonInbox )
803- }, context .UserAssignmentAPI ())
836+ }, context .UserAssignmentAPI (), checkTokenPublicOnly () )
804837 m .Group ("/user-id/{user-id}" , func () {
805838 m .Get ("" , activitypub .Person )
806839 m .Post ("/inbox" , activitypub .ReqHTTPSignature (), activitypub .PersonInbox )
807- }, context .UserIDAssignmentAPI ())
840+ }, context .UserIDAssignmentAPI (), checkTokenPublicOnly () )
808841 m .Group ("/actor" , func () {
809842 m .Get ("" , activitypub .Actor )
810843 m .Post ("/inbox" , activitypub .ActorInbox )
@@ -871,7 +904,7 @@ func Routes() *web.Route {
871904 }, reqSelfOrAdmin (), reqBasicOrRevProxyAuth ())
872905
873906 m .Get ("/activities/feeds" , user .ListUserActivityFeeds )
874- }, context .UserAssignmentAPI (), individualPermsChecker )
907+ }, context .UserAssignmentAPI (), checkTokenPublicOnly (), individualPermsChecker )
875908 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser ))
876909
877910 // Users (requires user scope)
@@ -891,7 +924,7 @@ func Routes() *web.Route {
891924 }
892925
893926 m .Get ("/subscriptions" , user .GetWatchedRepos )
894- }, context .UserAssignmentAPI ())
927+ }, context .UserAssignmentAPI (), checkTokenPublicOnly () )
895928 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser ), reqToken ())
896929
897930 // Users (requires user scope)
@@ -988,7 +1021,7 @@ func Routes() *web.Route {
9881021 m .Get ("" , user .IsStarring )
9891022 m .Put ("" , user .Star )
9901023 m .Delete ("" , user .Unstar )
991- }, repoAssignment ())
1024+ }, repoAssignment (), checkTokenPublicOnly () )
9921025 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryRepository ))
9931026 }
9941027 m .Get ("/times" , repo .ListMyTrackedTimes )
@@ -1019,12 +1052,14 @@ func Routes() *web.Route {
10191052
10201053 // Repositories (requires repo scope, org scope)
10211054 m .Post ("/org/{org}/repos" ,
1055+ // FIXME: we need org in context
10221056 tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization , auth_model .AccessTokenScopeCategoryRepository ),
10231057 reqToken (),
10241058 bind (api.CreateRepoOption {}),
10251059 repo .CreateOrgRepoDeprecated )
10261060
10271061 // requires repo scope
1062+ // FIXME: Don't expose repository id outside of the system
10281063 m .Combo ("/repositories/{id}" , reqToken (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryRepository )).Get (repo .GetByID )
10291064
10301065 // Repos (requires repo scope)
@@ -1305,7 +1340,7 @@ func Routes() *web.Route {
13051340 m .Post ("" , bind (api.UpdateRepoAvatarOption {}), repo .UpdateAvatar )
13061341 m .Delete ("" , repo .DeleteAvatar )
13071342 }, reqAdmin (), reqToken ())
1308- }, repoAssignment ())
1343+ }, repoAssignment (), checkTokenPublicOnly () )
13091344 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryRepository ))
13101345
13111346 // Notifications (requires notifications scope)
@@ -1314,7 +1349,7 @@ func Routes() *web.Route {
13141349 m .Combo ("/notifications" , reqToken ()).
13151350 Get (notify .ListRepoNotifications ).
13161351 Put (notify .ReadRepoNotifications )
1317- }, repoAssignment ())
1352+ }, repoAssignment (), checkTokenPublicOnly () )
13181353 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryNotification ))
13191354
13201355 // Issue (requires issue scope)
@@ -1428,7 +1463,7 @@ func Routes() *web.Route {
14281463 Patch (reqToken (), reqRepoWriter (unit .TypeIssues , unit .TypePullRequests ), bind (api.EditMilestoneOption {}), repo .EditMilestone ).
14291464 Delete (reqToken (), reqRepoWriter (unit .TypeIssues , unit .TypePullRequests ), repo .DeleteMilestone )
14301465 })
1431- }, repoAssignment ())
1466+ }, repoAssignment (), checkTokenPublicOnly () )
14321467 }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryIssue ))
14331468
14341469 // NOTE: these are Gitea package management API - see packages.CommonRoutes and packages.DockerContainerRoutes for endpoints that implement package manager APIs
@@ -1439,14 +1474,14 @@ func Routes() *web.Route {
14391474 m .Get ("/files" , reqToken (), packages .ListPackageFiles )
14401475 })
14411476 m .Get ("/" , reqToken (), packages .ListPackages )
1442- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryPackage ), context .UserAssignmentAPI (), context .PackageAssignmentAPI (), reqPackageAccess (perm .AccessModeRead ))
1477+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryPackage ), context .UserAssignmentAPI (), context .PackageAssignmentAPI (), reqPackageAccess (perm .AccessModeRead ), checkTokenPublicOnly () )
14431478
14441479 // Organizations
14451480 m .Get ("/user/orgs" , reqToken (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser , auth_model .AccessTokenScopeCategoryOrganization ), org .ListMyOrgs )
14461481 m .Group ("/users/{username}/orgs" , func () {
14471482 m .Get ("" , reqToken (), org .ListUserOrgs )
14481483 m .Get ("/{org}/permissions" , reqToken (), org .GetUserOrgsPermissions )
1449- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser , auth_model .AccessTokenScopeCategoryOrganization ), context .UserAssignmentAPI ())
1484+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser , auth_model .AccessTokenScopeCategoryOrganization ), context .UserAssignmentAPI (), checkTokenPublicOnly () )
14501485 m .Post ("/orgs" , tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ), reqToken (), bind (api.CreateOrgOption {}), org .Create )
14511486 m .Get ("/orgs" , org .GetAll , tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ))
14521487 m .Group ("/orgs/{org}" , func () {
@@ -1513,7 +1548,7 @@ func Routes() *web.Route {
15131548 m .Put ("/unblock/{username}" , org .UnblockUser )
15141549 }, context .UserAssignmentAPI ())
15151550 }, reqToken (), reqOrgOwnership ())
1516- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ), orgAssignment (true ))
1551+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ), orgAssignment (true ), checkTokenPublicOnly () )
15171552 m .Group ("/teams/{teamid}" , func () {
15181553 m .Combo ("" ).Get (reqToken (), org .GetTeam ).
15191554 Patch (reqToken (), reqOrgOwnership (), bind (api.EditTeamOption {}), org .EditTeam ).
@@ -1533,7 +1568,7 @@ func Routes() *web.Route {
15331568 Get (reqToken (), org .GetTeamRepo )
15341569 })
15351570 m .Get ("/activities/feeds" , org .ListTeamActivityFeeds )
1536- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ), orgAssignment (false , true ), reqToken (), reqTeamMembership ())
1571+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryOrganization ), orgAssignment (false , true ), reqToken (), reqTeamMembership (), checkTokenPublicOnly () )
15371572
15381573 m .Group ("/admin" , func () {
15391574 m .Group ("/cron" , func () {
0 commit comments