Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 5663c5e

Browse files
author
Noah Hanjun Lee
authored
Change the prefix of repos API (#136)
1 parent 140a4dc commit 5663c5e

File tree

6 files changed

+247
-164
lines changed

6 files changed

+247
-164
lines changed

internal/server/api/v1/repos/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type (
1818

1919
ListReposOfUser(ctx context.Context, u *ent.User, q, namespace, name string, sorted bool, page, perPage int) ([]*ent.Repo, error)
2020
FindRepoOfUserByID(ctx context.Context, u *ent.User, id string) (*ent.Repo, error)
21+
FindRepoOfUserByNamespaceName(ctx context.Context, u *ent.User, namespace, name string) (*ent.Repo, error)
2122
UpdateRepo(ctx context.Context, r *ent.Repo) (*ent.Repo, error)
2223
ActivateRepo(ctx context.Context, u *ent.User, r *ent.Repo, c *vo.WebhookConfig) (*ent.Repo, error)
2324
DeactivateRepo(ctx context.Context, u *ent.User, r *ent.Repo) (*ent.Repo, error)

internal/server/api/v1/repos/middleware.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,31 @@ func (rm *RepoMiddleware) RepoReadPerm() gin.HandlerFunc {
3333
ctx := c.Request.Context()
3434

3535
var (
36-
id = c.Param("id")
36+
namespace = c.Param("namespace")
37+
name = c.Param("name")
3738
)
3839

3940
v, _ := c.Get(gb.KeyUser)
4041
u := v.(*ent.User)
4142

42-
r, err := rm.i.FindRepoOfUserByID(ctx, u, id)
43+
r, err := rm.i.FindRepoOfUserByNamespaceName(ctx, u, namespace, name)
4344
if ent.IsNotFound(err) {
44-
rm.log.Warn("The repository is not found.", zap.String("repo_id", id), zap.Error(err))
45+
rm.log.Warn("The repository is not found.", zap.String("repo", namespace+"/"+name), zap.Error(err))
4546
gb.AbortWithErrorResponse(c, http.StatusNotFound, "The repository is not found.")
4647
return
4748
} else if err != nil {
48-
rm.log.Error("It has failed to get the repository.", zap.String("repo_id", id), zap.Error(err))
49+
rm.log.Error("It has failed to get the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
4950
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the repository.")
5051
return
5152
}
5253

5354
_, err = rm.i.FindPermOfRepo(ctx, r, u)
5455
if ent.IsNotFound(err) {
55-
rm.log.Warn("It is denied to access the repository.", zap.String("repo_id", id), zap.Error(err))
56+
rm.log.Warn("It is denied to access the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
5657
gb.AbortWithErrorResponse(c, http.StatusForbidden, "It is denied to access the repository.")
5758
return
5859
} else if err != nil {
59-
rm.log.Error("It has failed to get the permission.", zap.String("repoID", id), zap.Error(err))
60+
rm.log.Error("It has failed to get the permission.", zap.String("repo", namespace+"/"+name), zap.Error(err))
6061
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the permission.")
6162
return
6263
}
@@ -70,36 +71,37 @@ func (rm *RepoMiddleware) RepoWritePerm() gin.HandlerFunc {
7071
ctx := c.Request.Context()
7172

7273
var (
73-
id = c.Param("id")
74+
namespace = c.Param("namespace")
75+
name = c.Param("name")
7476
)
7577

7678
v, _ := c.Get(gb.KeyUser)
7779
u := v.(*ent.User)
7880

79-
r, err := rm.i.FindRepoOfUserByID(ctx, u, id)
81+
r, err := rm.i.FindRepoOfUserByNamespaceName(ctx, u, namespace, name)
8082
if ent.IsNotFound(err) {
81-
rm.log.Warn("The repository is not found.", zap.String("repo_id", id), zap.Error(err))
83+
rm.log.Warn("The repository is not found.", zap.String("repo", namespace+"/"+name), zap.Error(err))
8284
gb.AbortWithErrorResponse(c, http.StatusNotFound, "The repository is not found.")
8385
return
8486
} else if err != nil {
85-
rm.log.Error("It has failed to get the repository.", zap.String("repo_id", id), zap.Error(err))
87+
rm.log.Error("It has failed to get the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
8688
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the repository.")
8789
return
8890
}
8991

9092
p, err := rm.i.FindPermOfRepo(ctx, r, u)
9193
if ent.IsNotFound(err) {
92-
rm.log.Warn("It is denied to access the repository.", zap.String("repo_id", id), zap.Error(err))
94+
rm.log.Warn("It is denied to access the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
9395
gb.AbortWithErrorResponse(c, http.StatusForbidden, "It is denied to access the repository.")
9496
return
9597
} else if err != nil {
96-
rm.log.Error("It has failed to get the repository.", zap.String("repo_id", id), zap.Error(err))
98+
rm.log.Error("It has failed to get the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
9799
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the permission.")
98100
return
99101
}
100102

101103
if !(p.RepoPerm == perm.RepoPermWrite || p.RepoPerm == perm.RepoPermAdmin) {
102-
rm.log.Warn("The access is forbidden. Only write permission can access.", zap.String("repo_id", id))
104+
rm.log.Warn("The access is forbidden. Only write permission can access.", zap.String("repo", namespace+"/"+name))
103105
gb.AbortWithErrorResponse(c, http.StatusForbidden, "Only write permission can access.")
104106
return
105107
}
@@ -113,36 +115,37 @@ func (rm *RepoMiddleware) RepoAdminPerm() gin.HandlerFunc {
113115
ctx := c.Request.Context()
114116

115117
var (
116-
id = c.Param("id")
118+
namespace = c.Param("namespace")
119+
name = c.Param("name")
117120
)
118121

119122
v, _ := c.Get(gb.KeyUser)
120123
u := v.(*ent.User)
121124

122-
r, err := rm.i.FindRepoOfUserByID(ctx, u, id)
125+
r, err := rm.i.FindRepoOfUserByNamespaceName(ctx, u, namespace, name)
123126
if ent.IsNotFound(err) {
124-
rm.log.Warn("The repository is not found.", zap.String("repo_id", id), zap.Error(err))
127+
rm.log.Warn("The repository is not found.", zap.String("repo", namespace+"/"+name), zap.Error(err))
125128
gb.AbortWithErrorResponse(c, http.StatusNotFound, "The repository is not found.")
126129
return
127130
} else if err != nil {
128-
rm.log.Error("It has failed to get the repository.", zap.String("repo_id", id), zap.Error(err))
131+
rm.log.Error("It has failed to get the repository.", zap.String("repo", namespace+"/"+name), zap.Error(err))
129132
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the repository.")
130133
return
131134
}
132135

133136
p, err := rm.i.FindPermOfRepo(ctx, r, u)
134137
if ent.IsNotFound(err) {
135-
rm.log.Warn("It is denied to access the repo.", zap.String("repo_id", id), zap.Error(err))
138+
rm.log.Warn("It is denied to access the repo.", zap.String("repo", namespace+"/"+name), zap.Error(err))
136139
gb.AbortWithErrorResponse(c, http.StatusForbidden, "It is denied to access the repo.")
137140
return
138141
} else if err != nil {
139-
rm.log.Error("It has failed to get the permission.", zap.String("repo_id", id), zap.Error(err))
142+
rm.log.Error("It has failed to get the permission.", zap.String("repo", namespace+"/"+name), zap.Error(err))
140143
gb.AbortWithErrorResponse(c, http.StatusInternalServerError, "It has failed to get the permission.")
141144
return
142145
}
143146

144147
if p.RepoPerm != perm.RepoPermAdmin {
145-
rm.log.Warn("The access is forbidden. Only admin permission can access.", zap.String("repo_id", id))
148+
rm.log.Warn("The access is forbidden. Only admin permission can access.", zap.String("repo", namespace+"/"+name))
146149
gb.AbortWithErrorResponse(c, http.StatusForbidden, "Only admin permission can access.")
147150
return
148151
}

internal/server/api/v1/repos/middleware_test.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
1919

2020
t.Run("Return 403 error when the permission is read.", func(t *testing.T) {
2121
input := struct {
22-
RepoID string
22+
namespace string
23+
name string
2324
}{
24-
RepoID: "1",
25+
namespace: "octocat",
26+
name: "hello-world",
2527
}
2628

2729
ctrl := gomock.NewController(t)
@@ -30,17 +32,16 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
3032
t.Logf("It finds the repository.")
3133
m.
3234
EXPECT().
33-
FindRepoOfUserByID(ctx, gomock.AssignableToTypeOf(&ent.User{}), gomock.Eq(input.RepoID)).
35+
FindRepoOfUserByNamespaceName(ctx, gomock.AssignableToTypeOf(&ent.User{}), input.namespace, input.name).
3436
Return(&ent.Repo{
35-
ID: input.RepoID,
37+
Namespace: input.namespace,
38+
Name: input.name,
3639
}, nil)
3740

3841
t.Logf("It returns the read permission.")
3942
m.
4043
EXPECT().
41-
FindPermOfRepo(ctx, gomock.Eq(&ent.Repo{
42-
ID: input.RepoID,
43-
}), gomock.AssignableToTypeOf(&ent.User{})).
44+
FindPermOfRepo(ctx, gomock.AssignableToTypeOf(&ent.Repo{}), gomock.AssignableToTypeOf(&ent.User{})).
4445
Return(&ent.Perm{
4546
RepoPerm: perm.RepoPermRead,
4647
}, nil)
@@ -49,14 +50,14 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
4950
router := gin.New()
5051

5152
rm := NewRepoMiddleware(m)
52-
router.PATCH("/repos/:id", func(c *gin.Context) {
53+
router.PATCH("/repos/:namespace/:name", func(c *gin.Context) {
5354
// Mocking middlewares to return a user and a repository.
5455
c.Set(global.KeyUser, &ent.User{})
5556
}, rm.RepoWritePerm(), func(c *gin.Context) {
5657
c.Status(http.StatusOK)
5758
})
5859

59-
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s", input.RepoID), nil)
60+
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s/%s", input.namespace, input.name), nil)
6061

6162
w := httptest.NewRecorder()
6263
router.ServeHTTP(w, req)
@@ -68,9 +69,11 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
6869

6970
t.Run("Return 200 when the permission is write.", func(t *testing.T) {
7071
input := struct {
71-
RepoID string
72+
namespace string
73+
name string
7274
}{
73-
RepoID: "1",
75+
namespace: "octocat",
76+
name: "hello-world",
7477
}
7578

7679
ctrl := gomock.NewController(t)
@@ -79,17 +82,16 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
7982
t.Logf("It finds the repository.")
8083
m.
8184
EXPECT().
82-
FindRepoOfUserByID(ctx, gomock.AssignableToTypeOf(&ent.User{}), gomock.Eq(input.RepoID)).
85+
FindRepoOfUserByNamespaceName(ctx, gomock.AssignableToTypeOf(&ent.User{}), input.namespace, input.name).
8386
Return(&ent.Repo{
84-
ID: input.RepoID,
87+
Namespace: input.namespace,
88+
Name: input.name,
8589
}, nil)
8690

8791
t.Logf("It returns the read permission.")
8892
m.
8993
EXPECT().
90-
FindPermOfRepo(ctx, gomock.Eq(&ent.Repo{
91-
ID: input.RepoID,
92-
}), gomock.AssignableToTypeOf(&ent.User{})).
94+
FindPermOfRepo(ctx, gomock.AssignableToTypeOf(&ent.Repo{}), gomock.AssignableToTypeOf(&ent.User{})).
9395
Return(&ent.Perm{
9496
RepoPerm: perm.RepoPermWrite,
9597
}, nil)
@@ -98,14 +100,14 @@ func TestRepoMiddleware_RepoWritePerm(t *testing.T) {
98100
router := gin.New()
99101

100102
rm := NewRepoMiddleware(m)
101-
router.PATCH("/repos/:id", func(c *gin.Context) {
103+
router.PATCH("/repos/:namespace/:name", func(c *gin.Context) {
102104
// Mocking middlewares to return a user and a repository.
103105
c.Set(global.KeyUser, &ent.User{})
104106
}, rm.RepoWritePerm(), func(c *gin.Context) {
105107
c.Status(http.StatusOK)
106108
})
107109

108-
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s", input.RepoID), nil)
110+
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s/%s", input.namespace, input.name), nil)
109111

110112
w := httptest.NewRecorder()
111113
router.ServeHTTP(w, req)
@@ -121,9 +123,11 @@ func TestRepoMiddleware_RepoAdminPerm(t *testing.T) {
121123

122124
t.Run("Return 200 when the permission is admin.", func(t *testing.T) {
123125
input := struct {
124-
RepoID string
126+
namespace string
127+
name string
125128
}{
126-
RepoID: "1",
129+
namespace: "octocat",
130+
name: "hello-world",
127131
}
128132

129133
ctrl := gomock.NewController(t)
@@ -132,17 +136,16 @@ func TestRepoMiddleware_RepoAdminPerm(t *testing.T) {
132136
t.Logf("It finds the repository.")
133137
m.
134138
EXPECT().
135-
FindRepoOfUserByID(ctx, gomock.AssignableToTypeOf(&ent.User{}), gomock.Eq(input.RepoID)).
139+
FindRepoOfUserByNamespaceName(ctx, gomock.AssignableToTypeOf(&ent.User{}), input.namespace, input.name).
136140
Return(&ent.Repo{
137-
ID: input.RepoID,
141+
Namespace: input.namespace,
142+
Name: input.name,
138143
}, nil)
139144

140145
t.Logf("It returns the read permission.")
141146
m.
142147
EXPECT().
143-
FindPermOfRepo(ctx, gomock.Eq(&ent.Repo{
144-
ID: input.RepoID,
145-
}), gomock.AssignableToTypeOf(&ent.User{})).
148+
FindPermOfRepo(ctx, gomock.AssignableToTypeOf(&ent.Repo{}), gomock.AssignableToTypeOf(&ent.User{})).
146149
Return(&ent.Perm{
147150
RepoPerm: perm.RepoPermAdmin,
148151
}, nil)
@@ -151,14 +154,14 @@ func TestRepoMiddleware_RepoAdminPerm(t *testing.T) {
151154
router := gin.New()
152155

153156
rm := NewRepoMiddleware(m)
154-
router.PATCH("/repos/:id", func(c *gin.Context) {
157+
router.PATCH("/repos/:namespace/:name", func(c *gin.Context) {
155158
// Mocking middlewares to return a user and a repository.
156159
c.Set(global.KeyUser, &ent.User{})
157160
}, rm.RepoWritePerm(), func(c *gin.Context) {
158161
c.Status(http.StatusOK)
159162
})
160163

161-
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s", input.RepoID), nil)
164+
req, _ := http.NewRequest("PATCH", fmt.Sprintf("/repos/%s/%s", input.namespace, input.name), nil)
162165

163166
w := httptest.NewRecorder()
164167
router.ServeHTTP(w, req)

internal/server/api/v1/repos/mock/interactor.go

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/server/router.go

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -123,32 +123,32 @@ func NewRouter(c *RouterConfig) *gin.Engine {
123123
c.Interactor,
124124
)
125125
repov1.GET("", r.ListRepos)
126-
repov1.GET("/:id", rm.RepoReadPerm(), r.GetRepo)
127-
repov1.PATCH("/:id", rm.RepoAdminPerm(), r.UpdateRepo)
128-
repov1.GET("/:id/commits", rm.RepoReadPerm(), r.ListCommits)
129-
repov1.GET("/:id/commits/:sha", rm.RepoReadPerm(), r.GetCommit)
130-
repov1.GET("/:id/commits/:sha/statuses", rm.RepoReadPerm(), r.ListStatuses)
131-
repov1.GET("/:id/branches", rm.RepoReadPerm(), r.ListBranches)
132-
repov1.GET("/:id/branches/:branch", rm.RepoReadPerm(), r.GetBranch)
133-
repov1.GET("/:id/tags", rm.RepoReadPerm(), r.ListTags)
134-
repov1.GET("/:id/tags/:tag", rm.RepoReadPerm(), r.GetTag)
135-
repov1.GET("/:id/deployments", rm.RepoReadPerm(), r.ListDeployments)
136-
repov1.POST("/:id/deployments", rm.RepoWritePerm(), r.CreateDeployment)
137-
repov1.GET("/:id/deployments/:number", rm.RepoReadPerm(), r.GetDeploymentByNumber)
138-
repov1.PATCH("/:id/deployments/:number", rm.RepoWritePerm(), r.UpdateDeployment)
139-
repov1.GET("/:id/deployments/:number/changes", rm.RepoReadPerm(), r.ListDeploymentChanges)
140-
repov1.POST("/:id/deployments/:number/rollback", rm.RepoWritePerm(), r.RollbackDeployment)
141-
repov1.GET("/:id/deployments/:number/approvals", rm.RepoReadPerm(), r.ListApprovals)
142-
repov1.POST("/:id/deployments/:number/approvals", rm.RepoReadPerm(), r.CreateApproval)
143-
repov1.GET("/:id/deployments/:number/approval", rm.RepoReadPerm(), r.GetMyApproval)
144-
repov1.PATCH("/:id/deployments/:number/approval", rm.RepoReadPerm(), r.UpdateApproval)
145-
repov1.GET("/:id/approvals/:aid", rm.RepoReadPerm(), r.GetApproval)
146-
repov1.DELETE("/:id/approvals/:aid", rm.RepoReadPerm(), r.DeleteApproval)
147-
repov1.GET("/:id/locks", rm.RepoReadPerm(), r.ListLocks)
148-
repov1.POST("/:id/locks", rm.RepoWritePerm(), r.CreateLock)
149-
repov1.DELETE("/:id/locks/:lockID", rm.RepoWritePerm(), r.DeleteLock)
150-
repov1.GET("/:id/perms", rm.RepoReadPerm(), r.ListPerms)
151-
repov1.GET("/:id/config", rm.RepoReadPerm(), r.GetConfig)
126+
repov1.GET("/:namespace/:name", rm.RepoReadPerm(), r.GetRepo)
127+
repov1.PATCH("/:namespace/:name", rm.RepoAdminPerm(), r.UpdateRepo)
128+
repov1.GET("/:namespace/:name/commits", rm.RepoReadPerm(), r.ListCommits)
129+
repov1.GET("/:namespace/:name/commits/:sha", rm.RepoReadPerm(), r.GetCommit)
130+
repov1.GET("/:namespace/:name/commits/:sha/statuses", rm.RepoReadPerm(), r.ListStatuses)
131+
repov1.GET("/:namespace/:name/branches", rm.RepoReadPerm(), r.ListBranches)
132+
repov1.GET("/:namespace/:name/branches/:branch", rm.RepoReadPerm(), r.GetBranch)
133+
repov1.GET("/:namespace/:name/tags", rm.RepoReadPerm(), r.ListTags)
134+
repov1.GET("/:namespace/:name/tags/:tag", rm.RepoReadPerm(), r.GetTag)
135+
repov1.GET("/:namespace/:name/deployments", rm.RepoReadPerm(), r.ListDeployments)
136+
repov1.POST("/:namespace/:name/deployments", rm.RepoWritePerm(), r.CreateDeployment)
137+
repov1.GET("/:namespace/:name/deployments/:number", rm.RepoReadPerm(), r.GetDeploymentByNumber)
138+
repov1.PATCH("/:namespace/:name/deployments/:number", rm.RepoWritePerm(), r.UpdateDeployment)
139+
repov1.GET("/:namespace/:name/deployments/:number/changes", rm.RepoReadPerm(), r.ListDeploymentChanges)
140+
repov1.POST("/:namespace/:name/deployments/:number/rollback", rm.RepoWritePerm(), r.RollbackDeployment)
141+
repov1.GET("/:namespace/:name/deployments/:number/approvals", rm.RepoReadPerm(), r.ListApprovals)
142+
repov1.POST("/:namespace/:name/deployments/:number/approvals", rm.RepoReadPerm(), r.CreateApproval)
143+
repov1.GET("/:namespace/:name/deployments/:number/approval", rm.RepoReadPerm(), r.GetMyApproval)
144+
repov1.PATCH("/:namespace/:name/deployments/:number/approval", rm.RepoReadPerm(), r.UpdateApproval)
145+
repov1.GET("/:namespace/:name/approvals/:aid", rm.RepoReadPerm(), r.GetApproval)
146+
repov1.DELETE("/:namespace/:name/approvals/:aid", rm.RepoReadPerm(), r.DeleteApproval)
147+
repov1.GET("/:namespace/:name/locks", rm.RepoReadPerm(), r.ListLocks)
148+
repov1.POST("/:namespace/:name/locks", rm.RepoWritePerm(), r.CreateLock)
149+
repov1.DELETE("/:namespace/:name/locks/:lockID", rm.RepoWritePerm(), r.DeleteLock)
150+
repov1.GET("/:namespace/:name/perms", rm.RepoReadPerm(), r.ListPerms)
151+
repov1.GET("/:namespace/:name/config", rm.RepoReadPerm(), r.GetConfig)
152152
}
153153

154154
usersv1 := v1.Group("/users")

0 commit comments

Comments
 (0)