Skip to content

Commit d884312

Browse files
authored
Merge pull request #100 from ethantkoenig/develop
API endpoints for stars
2 parents 871c964 + 0834e49 commit d884312

File tree

5 files changed

+138
-34
lines changed

5 files changed

+138
-34
lines changed

models/user.go

+15
Original file line numberDiff line numberDiff line change
@@ -1179,3 +1179,18 @@ func UnfollowUser(userID, followID int64) (err error) {
11791179
}
11801180
return sess.Commit()
11811181
}
1182+
1183+
// GetStarredRepos returns the repos starred by a particular user
1184+
func GetStarredRepos(userID int64, private bool) ([]*Repository, error) {
1185+
sess := x.Where("star.uid=?", userID).
1186+
Join("LEFT", "star", "`repository`.id=`star`.repo_id")
1187+
if !private {
1188+
sess = sess.And("is_private=?", false)
1189+
}
1190+
repos := make([]*Repository, 0, 10)
1191+
err := sess.Find(&repos)
1192+
if err != nil {
1193+
return nil, err
1194+
}
1195+
return repos, nil
1196+
}

modules/context/api.go

+31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"strings"
1010

11+
"code.gitea.io/gitea/models"
1112
"code.gitea.io/gitea/modules/base"
1213
"code.gitea.io/gitea/modules/log"
1314
"code.gitea.io/gitea/modules/setting"
@@ -70,3 +71,33 @@ func APIContexter() macaron.Handler {
7071
c.Map(ctx)
7172
}
7273
}
74+
75+
// ExtractOwnerAndRepo returns a handler that populates the `Repo.Owner` and
76+
// `Repo.Repository` fields of an APIContext
77+
func ExtractOwnerAndRepo() macaron.Handler {
78+
return func(ctx *APIContext) {
79+
owner, err := models.GetUserByName(ctx.Params(":username"))
80+
if err != nil {
81+
if models.IsErrUserNotExist(err) {
82+
ctx.Error(422, "", err)
83+
} else {
84+
ctx.Error(500, "GetUserByName", err)
85+
}
86+
return
87+
}
88+
89+
repo, err := models.GetRepositoryByName(owner.ID, ctx.Params(":reponame"))
90+
if err != nil {
91+
if models.IsErrRepoNotExist(err) {
92+
ctx.Status(404)
93+
} else {
94+
ctx.Error(500, "GetRepositoryByName", err)
95+
}
96+
return
97+
}
98+
ctx.Repo.Owner = owner
99+
ctx.Data["Owner"] = owner
100+
ctx.Repo.Repository = repo
101+
ctx.Data["Repository"] = repo
102+
}
103+
}

routers/api/v1/api.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ func RegisterRoutes(m *macaron.Macaron) {
200200
m.Get("", user.ListFollowing)
201201
m.Get("/:target", user.CheckFollowing)
202202
})
203+
204+
m.Get("/starred", user.GetStarredRepos)
203205
})
204206
}, reqToken())
205207

@@ -221,6 +223,15 @@ func RegisterRoutes(m *macaron.Macaron) {
221223
m.Combo("/:id").Get(user.GetPublicKey).
222224
Delete(user.DeletePublicKey)
223225
})
226+
227+
m.Group("/starred", func() {
228+
m.Get("", user.GetMyStarredRepos)
229+
m.Group("/:username/:reponame", func() {
230+
m.Get("", user.IsStarring)
231+
m.Put("", user.Star)
232+
m.Delete("", user.Unstar)
233+
}, context.ExtractOwnerAndRepo())
234+
})
224235
}, reqToken())
225236

226237
// Repositories
@@ -234,7 +245,8 @@ func RegisterRoutes(m *macaron.Macaron) {
234245

235246
m.Group("/repos", func() {
236247
m.Post("/migrate", bind(auth.MigrateRepoForm{}), repo.Migrate)
237-
m.Combo("/:username/:reponame").Get(repo.Get).
248+
m.Combo("/:username/:reponame", context.ExtractOwnerAndRepo()).
249+
Get(repo.Get).
238250
Delete(repo.Delete)
239251

240252
m.Group("/:username/:reponame", func() {

routers/api/v1/repo/repo.go

+3-33
Original file line numberDiff line numberDiff line change
@@ -238,46 +238,16 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
238238
ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
239239
}
240240

241-
func parseOwnerAndRepo(ctx *context.APIContext) (*models.User, *models.Repository) {
242-
owner, err := models.GetUserByName(ctx.Params(":username"))
243-
if err != nil {
244-
if models.IsErrUserNotExist(err) {
245-
ctx.Error(422, "", err)
246-
} else {
247-
ctx.Error(500, "GetUserByName", err)
248-
}
249-
return nil, nil
250-
}
251-
252-
repo, err := models.GetRepositoryByName(owner.ID, ctx.Params(":reponame"))
253-
if err != nil {
254-
if models.IsErrRepoNotExist(err) {
255-
ctx.Status(404)
256-
} else {
257-
ctx.Error(500, "GetRepositoryByName", err)
258-
}
259-
return nil, nil
260-
}
261-
262-
return owner, repo
263-
}
264-
265241
// https://github.com/gogits/go-gogs-client/wiki/Repositories#get
266242
func Get(ctx *context.APIContext) {
267-
_, repo := parseOwnerAndRepo(ctx)
268-
if ctx.Written() {
269-
return
270-
}
271-
243+
repo := ctx.Repo.Repository
272244
ctx.JSON(200, repo.APIFormat(&api.Permission{true, true, true}))
273245
}
274246

275247
// https://github.com/gogits/go-gogs-client/wiki/Repositories#delete
276248
func Delete(ctx *context.APIContext) {
277-
owner, repo := parseOwnerAndRepo(ctx)
278-
if ctx.Written() {
279-
return
280-
}
249+
owner := ctx.Repo.Owner
250+
repo := ctx.Repo.Repository
281251

282252
if owner.IsOrganization() && !owner.IsOwnedBy(ctx.User.ID) {
283253
ctx.Error(403, "", "Given user is not owner of organization.")

routers/api/v1/user/star.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2016 The Gogs Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package user
6+
7+
import (
8+
api "code.gitea.io/sdk/gitea"
9+
10+
"code.gitea.io/gitea/models"
11+
"code.gitea.io/gitea/modules/context"
12+
)
13+
14+
// getStarredRepos returns the repos that the user with the specified userID has
15+
// starred
16+
func getStarredRepos(userID int64, private bool) ([]*api.Repository, error) {
17+
starredRepos, err := models.GetStarredRepos(userID, private)
18+
if err != nil {
19+
return nil, err
20+
}
21+
repos := make([]*api.Repository, len(starredRepos))
22+
for i, starred := range starredRepos {
23+
repos[i] = starred.APIFormat(&api.Permission{true, true, true})
24+
}
25+
return repos, nil
26+
}
27+
28+
// GetStarredRepos returns the repos that the user specified by the APIContext
29+
// has starred
30+
func GetStarredRepos(ctx *context.APIContext) {
31+
user := GetUserByParams(ctx)
32+
private := user.ID == ctx.User.ID
33+
repos, err := getStarredRepos(user.ID, private)
34+
if err != nil {
35+
ctx.Error(500, "getStarredRepos", err)
36+
}
37+
ctx.JSON(200, &repos)
38+
}
39+
40+
// GetMyStarredRepos returns the repos that the authenticated user has starred
41+
func GetMyStarredRepos(ctx *context.APIContext) {
42+
repos, err := getStarredRepos(ctx.User.ID, true)
43+
if err != nil {
44+
ctx.Error(500, "getStarredRepos", err)
45+
}
46+
ctx.JSON(200, &repos)
47+
}
48+
49+
// IsStarring returns whether the authenticated is starring the repo
50+
func IsStarring(ctx *context.APIContext) {
51+
if models.IsStaring(ctx.User.ID, ctx.Repo.Repository.ID) {
52+
ctx.Status(204)
53+
} else {
54+
ctx.Status(404)
55+
}
56+
}
57+
58+
// Star the repo specified in the APIContext, as the authenticated user
59+
func Star(ctx *context.APIContext) {
60+
err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
61+
if err != nil {
62+
ctx.Error(500, "StarRepo", err)
63+
return
64+
}
65+
ctx.Status(204)
66+
}
67+
68+
// Unstar the repo specified in the APIContext, as the authenticated user
69+
func Unstar(ctx *context.APIContext) {
70+
err := models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
71+
if err != nil {
72+
ctx.Error(500, "StarRepo", err)
73+
return
74+
}
75+
ctx.Status(204)
76+
}

0 commit comments

Comments
 (0)