@@ -212,6 +212,11 @@ func repoAssignment() func(ctx *context.APIContext) {
212212 ctx .APIErrorNotFound ()
213213 return
214214 }
215+
216+ if ! ctx .TokenCanAccessRepo (repo ) {
217+ ctx .APIErrorNotFound ()
218+ return
219+ }
215220 }
216221}
217222
@@ -249,51 +254,66 @@ func checkTokenPublicOnly() func(ctx *context.APIContext) {
249254 return
250255 }
251256
252- // public Only permission check
253- switch {
254- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryRepository ):
255- if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
256- ctx .APIError (http .StatusForbidden , "token scope is limited to public repos" )
257- return
258- }
259- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryIssue ):
260- if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
261- ctx .APIError (http .StatusForbidden , "token scope is limited to public issues" )
262- return
263- }
264- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryOrganization ):
265- if ctx .Org .Organization != nil && ctx .Org .Organization .Visibility != api .VisibleTypePublic {
266- ctx .APIError (http .StatusForbidden , "token scope is limited to public orgs" )
267- return
268- }
269- if ctx .ContextUser != nil && ctx .ContextUser .IsOrganization () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
270- ctx .APIError (http .StatusForbidden , "token scope is limited to public orgs" )
271- return
272- }
273- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryUser ):
274- if ctx .ContextUser != nil && ctx .ContextUser .IsTokenAccessAllowed () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
275- ctx .APIError (http .StatusForbidden , "token scope is limited to public users" )
276- return
277- }
278- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryActivityPub ):
279- if ctx .ContextUser != nil && ctx .ContextUser .IsTokenAccessAllowed () && ctx .ContextUser .Visibility != api .VisibleTypePublic {
280- ctx .APIError (http .StatusForbidden , "token scope is limited to public activitypub" )
281- return
282- }
283- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryNotification ):
284- if ctx .Repo .Repository != nil && ctx .Repo .Repository .IsPrivate {
285- ctx .APIError (http .StatusForbidden , "token scope is limited to public notifications" )
286- return
287- }
288- case auth_model .ContainsCategory (requiredScopeCategories , auth_model .AccessTokenScopeCategoryPackage ):
289- if ctx .Package != nil && ctx .Package .Owner .Visibility .IsPrivate () {
290- ctx .APIError (http .StatusForbidden , "token scope is limited to public packages" )
291- return
257+ for _ , category := range requiredScopeCategories {
258+ switch category {
259+ case auth_model .AccessTokenScopeCategoryRepository :
260+ if ! ctx .TokenCanAccessRepo (ctx .Repo .Repository ) {
261+ ctx .APIError (http .StatusForbidden , "token scope is limited to public repos" )
262+ return
263+ }
264+ case auth_model .AccessTokenScopeCategoryIssue :
265+ if ! ctx .TokenCanAccessRepo (ctx .Repo .Repository ) {
266+ ctx .APIError (http .StatusForbidden , "token scope is limited to public issues" )
267+ return
268+ }
269+ case auth_model .AccessTokenScopeCategoryOrganization :
270+ orgPrivate := ctx .Org .Organization != nil && ! ctx .Org .Organization .Visibility .IsPublic ()
271+ userOrgPrivate := ctx .ContextUser != nil && ctx .ContextUser .IsOrganization () && ! ctx .ContextUser .Visibility .IsPublic ()
272+ if orgPrivate || userOrgPrivate {
273+ ctx .APIError (http .StatusForbidden , "token scope is limited to public orgs" )
274+ return
275+ }
276+ case auth_model .AccessTokenScopeCategoryUser :
277+ if ctx .ContextUser != nil && ctx .ContextUser .IsTokenAccessAllowed () && ! ctx .ContextUser .Visibility .IsPublic () {
278+ ctx .APIError (http .StatusForbidden , "token scope is limited to public users" )
279+ return
280+ }
281+ case auth_model .AccessTokenScopeCategoryActivityPub :
282+ if ctx .ContextUser != nil && ctx .ContextUser .IsTokenAccessAllowed () && ! ctx .ContextUser .Visibility .IsPublic () {
283+ ctx .APIError (http .StatusForbidden , "token scope is limited to public activitypub" )
284+ return
285+ }
286+ case auth_model .AccessTokenScopeCategoryNotification :
287+ if ! ctx .TokenCanAccessRepo (ctx .Repo .Repository ) {
288+ ctx .APIError (http .StatusForbidden , "token scope is limited to public notifications" )
289+ return
290+ }
291+ case auth_model .AccessTokenScopeCategoryPackage :
292+ if ctx .Package != nil && ctx .Package .Owner .Visibility .IsPrivate () {
293+ ctx .APIError (http .StatusForbidden , "token scope is limited to public packages" )
294+ return
295+ }
292296 }
293297 }
294298 }
295299}
296300
301+ func rejectPublicOnly () func (ctx * context.APIContext ) {
302+ return func (ctx * context.APIContext ) {
303+ if ! ctx .PublicOnly {
304+ return
305+ }
306+
307+ ctx .APIError (http .StatusForbidden , "this endpoint is not available for public-only tokens" )
308+ }
309+ }
310+
311+ func contextAuthenticatedUser () func (ctx * context.APIContext ) {
312+ return func (ctx * context.APIContext ) {
313+ ctx .ContextUser = ctx .Doer
314+ }
315+ }
316+
297317// if a token is being used for auth, we check that it contains the required scope
298318// if a token is not being used, reqToken will enforce other sign in methods
299319func tokenRequiresScopes (requiredScopeCategories ... auth_model.AccessTokenScopeCategory ) func (ctx * context.APIContext ) {
@@ -957,6 +977,8 @@ func Routes() *web.Router {
957977 })
958978
959979 // Notifications (requires 'notifications' scope)
980+ // The notifications API is not available for public-only tokens because a user's notifications mix
981+ // public and private repository events in the same mailbox.
960982 m .Group ("/notifications" , func () {
961983 m .Combo ("" ).
962984 Get (reqToken (), notify .ListNotifications ).
@@ -965,7 +987,7 @@ func Routes() *web.Router {
965987 m .Combo ("/threads/{id}" ).
966988 Get (reqToken (), notify .GetThread ).
967989 Patch (reqToken (), notify .ReadThread )
968- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryNotification ))
990+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryNotification ), rejectPublicOnly () )
969991
970992 // Users (requires user scope)
971993 m .Group ("/users" , func () {
@@ -1013,8 +1035,9 @@ func Routes() *web.Router {
10131035 m .Group ("/settings" , func () {
10141036 m .Get ("" , user .GetUserSettings )
10151037 m .Patch ("" , bind (api.UserSettingsOptions {}), user .UpdateUserSettings )
1016- }, reqToken ())
1017- m .Combo ("/emails" ).
1038+ }, rejectPublicOnly ())
1039+ // Email addresses are always private account data.
1040+ m .Combo ("/emails" , rejectPublicOnly ()).
10181041 Get (user .ListEmails ).
10191042 Post (bind (api.CreateEmailOption {}), user .AddEmail ).
10201043 Delete (bind (api.DeleteEmailOption {}), user .DeleteEmail )
@@ -1046,7 +1069,7 @@ func Routes() *web.Router {
10461069
10471070 m .Get ("/runs" , reqToken (), user .ListWorkflowRuns )
10481071 m .Get ("/jobs" , reqToken (), user .ListWorkflowJobs )
1049- })
1072+ }, rejectPublicOnly () )
10501073
10511074 m .Get ("/followers" , user .ListMyFollowers )
10521075 m .Group ("/following" , func () {
@@ -1064,7 +1087,7 @@ func Routes() *web.Router {
10641087 Post (bind (api.CreateKeyOption {}), user .CreatePublicKey )
10651088 m .Combo ("/{id}" ).Get (user .GetPublicKey ).
10661089 Delete (user .DeletePublicKey )
1067- })
1090+ }, rejectPublicOnly () )
10681091
10691092 // (admin:application scope)
10701093 m .Group ("/applications" , func () {
@@ -1075,21 +1098,21 @@ func Routes() *web.Router {
10751098 Delete (user .DeleteOauth2Application ).
10761099 Patch (bind (api.CreateOAuth2ApplicationOptions {}), user .UpdateOauth2Application ).
10771100 Get (user .GetOauth2Application )
1078- })
1101+ }, rejectPublicOnly () )
10791102
10801103 // (admin:gpg_key scope)
10811104 m .Group ("/gpg_keys" , func () {
10821105 m .Combo ("" ).Get (user .ListMyGPGKeys ).
10831106 Post (bind (api.CreateGPGKeyOption {}), user .CreateGPGKey )
10841107 m .Combo ("/{id}" ).Get (user .GetGPGKey ).
10851108 Delete (user .DeleteGPGKey )
1086- })
1087- m .Get ("/gpg_key_token" , user .GetVerificationToken )
1088- m .Post ("/gpg_key_verify" , bind (api.VerifyGPGKeyOption {}), user .VerifyUserGPGKey )
1109+ }, rejectPublicOnly () )
1110+ m .Get ("/gpg_key_token" , rejectPublicOnly (), user .GetVerificationToken )
1111+ m .Post ("/gpg_key_verify" , rejectPublicOnly (), bind (api.VerifyGPGKeyOption {}), user .VerifyUserGPGKey )
10891112
10901113 // (repo scope)
10911114 m .Combo ("/repos" , tokenRequiresScopes (auth_model .AccessTokenScopeCategoryRepository )).Get (user .ListMyRepos ).
1092- Post (bind (api.CreateRepoOption {}), repo .Create )
1115+ Post (rejectPublicOnly (), bind (api.CreateRepoOption {}), repo .Create )
10931116
10941117 // (repo scope)
10951118 m .Group ("/starred" , func () {
@@ -1100,22 +1123,22 @@ func Routes() *web.Router {
11001123 m .Delete ("" , user .Unstar )
11011124 }, repoAssignment (), checkTokenPublicOnly ())
11021125 }, reqStarsEnabled (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryRepository ))
1103- m .Get ("/times" , repo .ListMyTrackedTimes )
1104- m .Get ("/stopwatches" , repo .GetStopwatches )
1126+ m .Get ("/times" , rejectPublicOnly (), repo .ListMyTrackedTimes )
1127+ m .Get ("/stopwatches" , rejectPublicOnly (), repo .GetStopwatches )
11051128 m .Get ("/subscriptions" , user .GetMyWatchedRepos )
1106- m .Get ("/teams" , org .ListUserTeams )
1129+ m .Get ("/teams" , rejectPublicOnly (), org .ListUserTeams )
11071130 m .Group ("/hooks" , func () {
11081131 m .Combo ("" ).Get (user .ListHooks ).
11091132 Post (bind (api.CreateHookOption {}), user .CreateHook )
11101133 m .Combo ("/{id}" ).Get (user .GetHook ).
11111134 Patch (bind (api.EditHookOption {}), user .EditHook ).
11121135 Delete (user .DeleteHook )
1113- }, reqWebhooksEnabled ())
1136+ }, reqWebhooksEnabled (), rejectPublicOnly () )
11141137
11151138 m .Group ("/avatar" , func () {
11161139 m .Post ("" , bind (api.UpdateUserAvatarOption {}), user .UpdateAvatar )
11171140 m .Delete ("" , user .DeleteAvatar )
1118- })
1141+ }, rejectPublicOnly () )
11191142
11201143 m .Group ("/blocks" , func () {
11211144 m .Get ("" , user .ListBlocks )
@@ -1124,8 +1147,8 @@ func Routes() *web.Router {
11241147 m .Put ("" , user .BlockUser )
11251148 m .Delete ("" , user .UnblockUser )
11261149 }, context .UserAssignmentAPI (), checkTokenPublicOnly ())
1127- })
1128- }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser ), reqToken ())
1150+ }, rejectPublicOnly () )
1151+ }, tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser ), reqToken (), contextAuthenticatedUser (), checkTokenPublicOnly () )
11291152
11301153 // Repositories (requires repo scope, org scope)
11311154 m .Post ("/org/{org}/repos" ,
@@ -1601,7 +1624,7 @@ func Routes() *web.Router {
16011624 }, reqToken (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryPackage ), context .UserAssignmentAPI (), context .PackageAssignmentAPI (), reqPackageAccess (perm .AccessModeRead ), checkTokenPublicOnly ())
16021625
16031626 // Organizations
1604- m .Get ("/user/orgs" , reqToken (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser , auth_model .AccessTokenScopeCategoryOrganization ), org .ListMyOrgs )
1627+ m .Get ("/user/orgs" , reqToken (), tokenRequiresScopes (auth_model .AccessTokenScopeCategoryUser , auth_model .AccessTokenScopeCategoryOrganization ), checkTokenPublicOnly (), org .ListMyOrgs )
16051628 m .Group ("/users/{username}/orgs" , func () {
16061629 m .Get ("" , reqToken (), org .ListUserOrgs )
16071630 m .Get ("/{org}/permissions" , reqToken (), org .GetUserOrgsPermissions )
0 commit comments