Skip to content

Commit 0df053f

Browse files
committed
add token scope
1 parent 899efca commit 0df053f

File tree

4 files changed

+41
-19
lines changed

4 files changed

+41
-19
lines changed

models/auth/access_token_scope.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
AccessTokenScopeCategoryIssue
2525
AccessTokenScopeCategoryRepository
2626
AccessTokenScopeCategoryUser
27+
AccessTokenScopeCategoryProject
2728
)
2829

2930
// AllAccessTokenScopeCategories contains all access token scope categories
@@ -37,6 +38,7 @@ var AllAccessTokenScopeCategories = []AccessTokenScopeCategory{
3738
AccessTokenScopeCategoryIssue,
3839
AccessTokenScopeCategoryRepository,
3940
AccessTokenScopeCategoryUser,
41+
AccessTokenScopeCategoryProject,
4042
}
4143

4244
// AccessTokenScopeLevel represents the access levels without a given scope category
@@ -82,6 +84,9 @@ const (
8284

8385
AccessTokenScopeReadUser AccessTokenScope = "read:user"
8486
AccessTokenScopeWriteUser AccessTokenScope = "write:user"
87+
88+
AccessTokenScopeReadProject AccessTokenScope = "read:project"
89+
AccessTokenScopeWriteProject AccessTokenScope = "write:project"
8590
)
8691

8792
// accessTokenScopeBitmap represents a bitmap of access token scopes.
@@ -124,6 +129,9 @@ const (
124129
accessTokenScopeReadUserBits accessTokenScopeBitmap = 1 << iota
125130
accessTokenScopeWriteUserBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadUserBits
126131

132+
accessTokenScopeReadProjectBits accessTokenScopeBitmap = 1 << iota
133+
accessTokenScopeWriteProjectBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadProjectBits
134+
127135
// The current implementation only supports up to 64 token scopes.
128136
// If we need to support > 64 scopes,
129137
// refactoring the whole implementation in this file (and only this file) is needed.
@@ -142,6 +150,7 @@ var allAccessTokenScopes = []AccessTokenScope{
142150
AccessTokenScopeWriteIssue, AccessTokenScopeReadIssue,
143151
AccessTokenScopeWriteRepository, AccessTokenScopeReadRepository,
144152
AccessTokenScopeWriteUser, AccessTokenScopeReadUser,
153+
AccessTokenScopeWriteProject, AccessTokenScopeReadProject,
145154
}
146155

147156
// allAccessTokenScopeBits contains all access token scopes.
@@ -166,6 +175,8 @@ var allAccessTokenScopeBits = map[AccessTokenScope]accessTokenScopeBitmap{
166175
AccessTokenScopeWriteRepository: accessTokenScopeWriteRepositoryBits,
167176
AccessTokenScopeReadUser: accessTokenScopeReadUserBits,
168177
AccessTokenScopeWriteUser: accessTokenScopeWriteUserBits,
178+
AccessTokenScopeReadProject: accessTokenScopeReadProjectBits,
179+
AccessTokenScopeWriteProject: accessTokenScopeWriteProjectBits,
169180
}
170181

171182
// readAccessTokenScopes maps a scope category to the read permission scope
@@ -180,6 +191,7 @@ var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]A
180191
AccessTokenScopeCategoryIssue: AccessTokenScopeReadIssue,
181192
AccessTokenScopeCategoryRepository: AccessTokenScopeReadRepository,
182193
AccessTokenScopeCategoryUser: AccessTokenScopeReadUser,
194+
AccessTokenScopeCategoryProject: AccessTokenScopeReadProject,
183195
},
184196
Write: {
185197
AccessTokenScopeCategoryActivityPub: AccessTokenScopeWriteActivityPub,
@@ -191,6 +203,7 @@ var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]A
191203
AccessTokenScopeCategoryIssue: AccessTokenScopeWriteIssue,
192204
AccessTokenScopeCategoryRepository: AccessTokenScopeWriteRepository,
193205
AccessTokenScopeCategoryUser: AccessTokenScopeWriteUser,
206+
AccessTokenScopeCategoryProject: AccessTokenScopeWriteProject,
194207
},
195208
}
196209

routers/api/v1/api.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,13 @@ func Routes() *web.Router {
10421042

10431043
m.Get("/subscriptions", user.GetWatchedRepos)
10441044
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
1045+
1046+
m.Group("/{username}", func() {
1047+
m.Group("/projects", func() {
1048+
m.Get("", projects.ListUserProjects)
1049+
m.Post("", bind(api.NewProjectOption{}), projects.CreateUserProject)
1050+
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryProject))
1051+
}, context.UserAssignmentAPI())
10451052
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
10461053

10471054
// Users (requires user scope)
@@ -1162,11 +1169,6 @@ func Routes() *web.Router {
11621169
m.Delete("", user.UnblockUser)
11631170
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
11641171
})
1165-
1166-
m.Group("/projects", func() {
1167-
m.Get("", projects.ListUserProjects)
1168-
m.Post("", bind(api.NewProjectOption{}), projects.CreateUserProject)
1169-
})
11701172
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
11711173

11721174
// Repositories (requires repo scope, org scope)
@@ -1476,7 +1478,7 @@ func Routes() *web.Router {
14761478

14771479
m.Group("/projects", func() {
14781480
m.Post("", bind(api.NewProjectOption{}), projects.CreateRepoProject)
1479-
})
1481+
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryProject))
14801482
}, repoAssignment(), checkTokenPublicOnly())
14811483
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
14821484

@@ -1701,7 +1703,7 @@ func Routes() *web.Router {
17011703
m.Group("/projects", func() {
17021704
m.Post("", bind(api.NewProjectOption{}), projects.CreateOrgProject)
17031705
m.Get("", projects.ListOrgProjects)
1704-
})
1706+
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryProject))
17051707
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true), checkTokenPublicOnly())
17061708
m.Group("/teams/{teamid}", func() {
17071709
m.Combo("").Get(reqToken(), org.GetTeam).
@@ -1724,6 +1726,13 @@ func Routes() *web.Router {
17241726
m.Get("/activities/feeds", org.ListTeamActivityFeeds)
17251727
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(false, true), reqToken(), reqTeamMembership(), checkTokenPublicOnly())
17261728

1729+
// Projects
1730+
m.Group("/projects", func() {
1731+
m.Get("{project_id}", projects.GetProject)
1732+
m.Patch("{project_id}", bind(api.UpdateProjectOption{}), projects.UpdateProject)
1733+
m.Delete("{project_id}", projects.DeleteProject)
1734+
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryProject), reqToken())
1735+
17271736
m.Group("/admin", func() {
17281737
m.Group("/cron", func() {
17291738
m.Get("", admin.ListCronTasks)

routers/api/v1/projects/project.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func GetProject(ctx *context.APIContext) {
158158
// "$ref": "#/responses/forbidden"
159159
// "404":
160160
// "$ref": "#/responses/notFound"
161-
project, err := project_model.GetProjectByID(ctx, ctx.FormInt64("id"))
161+
project, err := project_model.GetProjectByID(ctx, ctx.FormInt64("project_id"))
162162
if err != nil {
163163
if project_model.IsErrProjectNotExist(err) {
164164
ctx.APIError(http.StatusNotFound, err)
@@ -202,7 +202,7 @@ func UpdateProject(ctx *context.APIContext) {
202202
// "404":
203203
// "$ref": "#/responses/notFound"
204204
form := web.GetForm(ctx).(*api.UpdateProjectOption)
205-
project, err := project_model.GetProjectByID(ctx, ctx.FormInt64("id"))
205+
project, err := project_model.GetProjectByID(ctx, ctx.FormInt64("project_id"))
206206
if err != nil {
207207
if project_model.IsErrProjectNotExist(err) {
208208
ctx.APIError(http.StatusNotFound, err)
@@ -249,7 +249,7 @@ func DeleteProject(ctx *context.APIContext) {
249249
// "404":
250250
// "$ref": "#/responses/notFound"
251251

252-
if err := project_model.DeleteProjectByID(ctx, ctx.FormInt64("id")); err != nil {
252+
if err := project_model.DeleteProjectByID(ctx, ctx.FormInt64("project_id")); err != nil {
253253
ctx.APIErrorInternal(err)
254254
return
255255
}

tests/integration/api_project_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ func TestAPICreateUserProject(t *testing.T) {
2323
const title, description = "project_name", "project_description"
2424
templateType := project_model.TemplateTypeBasicKanban.ToString()
2525

26-
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteIssue, auth_model.AccessTokenScopeWriteUser)
26+
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteProject, auth_model.AccessTokenScopeWriteUser)
2727

28-
req := NewRequestWithJSON(t, "POST", "/api/v1/user/projects", &api.NewProjectOption{
28+
req := NewRequestWithJSON(t, "POST", "/api/v1/users/user2/projects", &api.NewProjectOption{
2929
Name: title,
3030
Body: description,
3131
TemplateType: templateType,
@@ -91,7 +91,7 @@ func TestAPIListUserProjects(t *testing.T) {
9191
defer tests.PrepareTestEnv(t)()
9292

9393
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopeReadIssue)
94-
link, _ := url.Parse("/api/v1/user/projects")
94+
link, _ := url.Parse("/api/v1/users/user2/projects")
9595

9696
req := NewRequest(t, "GET", link.String()).AddTokenAuth(token)
9797
var apiProjects []*api.Project
@@ -134,8 +134,8 @@ func TestAPIListRepoProjects(t *testing.T) {
134134

135135
func TestAPIGetProject(t *testing.T) {
136136
defer tests.PrepareTestEnv(t)()
137-
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopeReadIssue)
138-
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 1))
137+
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadProject)
138+
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 4))
139139

140140
req := NewRequest(t, "GET", link.String()).AddTokenAuth(token)
141141
var apiProject *api.Project
@@ -149,8 +149,8 @@ func TestAPIGetProject(t *testing.T) {
149149

150150
func TestAPIUpdateProject(t *testing.T) {
151151
defer tests.PrepareTestEnv(t)()
152-
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteIssue)
153-
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 1))
152+
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteProject)
153+
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 4))
154154

155155
req := NewRequestWithJSON(t, "PATCH", link.String(), &api.UpdateProjectOption{Name: "First project updated"}).AddTokenAuth(token)
156156

@@ -163,8 +163,8 @@ func TestAPIUpdateProject(t *testing.T) {
163163

164164
func TestAPIDeleteProject(t *testing.T) {
165165
defer tests.PrepareTestEnv(t)()
166-
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteIssue)
167-
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 1))
166+
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteProject)
167+
link, _ := url.Parse(fmt.Sprintf("/api/v1/projects/%d", 4))
168168

169169
req := NewRequest(t, "DELETE", link.String()).AddTokenAuth(token)
170170

0 commit comments

Comments
 (0)