mirror of
https://github.com/gogs/gogs.git
synced 2026-05-07 08:57:08 +02:00
internal: move packages under this directory (#5836)
* Rename pkg -> internal * Rename routes -> route * Move route -> internal/route * Rename models -> db * Move db -> internal/db * Fix route2 -> route * Move cmd -> internal/cmd * Bump version
This commit is contained in:
17
internal/route/api/v1/admin/org.go
Normal file
17
internal/route/api/v1/admin/org.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
org2 "gogs.io/gogs/internal/route/api/v1/org"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
)
|
||||
|
||||
func CreateOrg(c *context.APIContext, form api.CreateOrgOption) {
|
||||
org2.CreateOrgForUser(c, form, user2.GetUserByParams(c))
|
||||
}
|
||||
46
internal/route/api/v1/admin/org_repo.go
Normal file
46
internal/route/api/v1/admin/org_repo.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
func GetRepositoryByParams(c *context.APIContext) *db.Repository {
|
||||
repo, err := db.GetRepositoryByName(c.Org.Team.OrgID, c.Params(":reponame"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
|
||||
return nil
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func AddTeamRepository(c *context.APIContext) {
|
||||
repo := GetRepositoryByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
if err := c.Org.Team.AddRepository(repo); err != nil {
|
||||
c.ServerError("AddRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func RemoveTeamRepository(c *context.APIContext) {
|
||||
repo := GetRepositoryByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
if err := c.Org.Team.RemoveRepository(repo.ID); err != nil {
|
||||
c.ServerError("RemoveRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
62
internal/route/api/v1/admin/org_team.go
Normal file
62
internal/route/api/v1/admin/org_team.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func CreateTeam(c *context.APIContext, form api.CreateTeamOption) {
|
||||
team := &db.Team{
|
||||
OrgID: c.Org.Organization.ID,
|
||||
Name: form.Name,
|
||||
Description: form.Description,
|
||||
Authorize: db.ParseAccessMode(form.Permission),
|
||||
}
|
||||
if err := db.NewTeam(team); err != nil {
|
||||
if db.IsErrTeamAlreadyExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("NewTeam", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, convert2.ToTeam(team))
|
||||
}
|
||||
|
||||
func AddTeamMember(c *context.APIContext) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
if err := c.Org.Team.AddMember(u.ID); err != nil {
|
||||
c.ServerError("AddMember", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func RemoveTeamMember(c *context.APIContext) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.Org.Team.RemoveMember(u.ID); err != nil {
|
||||
c.ServerError("RemoveMember", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
22
internal/route/api/v1/admin/repo.go
Normal file
22
internal/route/api/v1/admin/repo.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
repo2 "gogs.io/gogs/internal/route/api/v1/repo"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
)
|
||||
|
||||
func CreateRepo(c *context.APIContext, form api.CreateRepoOption) {
|
||||
owner := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
repo2.CreateUserRepo(c, owner, form)
|
||||
}
|
||||
159
internal/route/api/v1/admin/user.go
Normal file
159
internal/route/api/v1/admin/user.go
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
"net/http"
|
||||
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/mailer"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func parseLoginSource(c *context.APIContext, u *db.User, sourceID int64, loginName string) {
|
||||
if sourceID == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
source, err := db.GetLoginSourceByID(sourceID)
|
||||
if err != nil {
|
||||
if errors.IsLoginSourceNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("GetLoginSourceByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
u.LoginType = source.Type
|
||||
u.LoginSource = source.ID
|
||||
u.LoginName = loginName
|
||||
}
|
||||
|
||||
func CreateUser(c *context.APIContext, form api.CreateUserOption) {
|
||||
u := &db.User{
|
||||
Name: form.Username,
|
||||
FullName: form.FullName,
|
||||
Email: form.Email,
|
||||
Passwd: form.Password,
|
||||
IsActive: true,
|
||||
LoginType: db.LOGIN_PLAIN,
|
||||
}
|
||||
|
||||
parseLoginSource(c, u, form.SourceID, form.LoginName)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.CreateUser(u); err != nil {
|
||||
if db.IsErrUserAlreadyExist(err) ||
|
||||
db.IsErrEmailAlreadyUsed(err) ||
|
||||
db.IsErrNameReserved(err) ||
|
||||
db.IsErrNamePatternNotAllowed(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("CreateUser", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
log.Trace("Account created by admin %q: %s", c.User.Name, u.Name)
|
||||
|
||||
// Send email notification.
|
||||
if form.SendNotify && setting.MailService != nil {
|
||||
mailer.SendRegisterNotifyMail(c.Context.Context, db.NewMailerUser(u))
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, u.APIFormat())
|
||||
}
|
||||
|
||||
func EditUser(c *context.APIContext, form api.EditUserOption) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
parseLoginSource(c, u, form.SourceID, form.LoginName)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Password) > 0 {
|
||||
u.Passwd = form.Password
|
||||
var err error
|
||||
if u.Salt, err = db.GetUserSalt(); err != nil {
|
||||
c.ServerError("GetUserSalt", err)
|
||||
return
|
||||
}
|
||||
u.EncodePasswd()
|
||||
}
|
||||
|
||||
u.LoginName = form.LoginName
|
||||
u.FullName = form.FullName
|
||||
u.Email = form.Email
|
||||
u.Website = form.Website
|
||||
u.Location = form.Location
|
||||
if form.Active != nil {
|
||||
u.IsActive = *form.Active
|
||||
}
|
||||
if form.Admin != nil {
|
||||
u.IsAdmin = *form.Admin
|
||||
}
|
||||
if form.AllowGitHook != nil {
|
||||
u.AllowGitHook = *form.AllowGitHook
|
||||
}
|
||||
if form.AllowImportLocal != nil {
|
||||
u.AllowImportLocal = *form.AllowImportLocal
|
||||
}
|
||||
if form.MaxRepoCreation != nil {
|
||||
u.MaxRepoCreation = *form.MaxRepoCreation
|
||||
}
|
||||
|
||||
if err := db.UpdateUser(u); err != nil {
|
||||
if db.IsErrEmailAlreadyUsed(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("UpdateUser", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
log.Trace("Account profile updated by admin %q: %s", c.User.Name, u.Name)
|
||||
|
||||
c.JSONSuccess(u.APIFormat())
|
||||
}
|
||||
|
||||
func DeleteUser(c *context.APIContext) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DeleteUser(u); err != nil {
|
||||
if db.IsErrUserOwnRepos(err) ||
|
||||
db.IsErrUserHasOrgs(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("DeleteUser", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
log.Trace("Account deleted by admin(%s): %s", c.User.Name, u.Name)
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
user2.CreateUserPublicKey(c, form, u.ID)
|
||||
}
|
||||
406
internal/route/api/v1/api.go
Normal file
406
internal/route/api/v1/api.go
Normal file
@@ -0,0 +1,406 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
admin2 "gogs.io/gogs/internal/route/api/v1/admin"
|
||||
misc2 "gogs.io/gogs/internal/route/api/v1/misc"
|
||||
org2 "gogs.io/gogs/internal/route/api/v1/org"
|
||||
repo2 "gogs.io/gogs/internal/route/api/v1/repo"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/form"
|
||||
)
|
||||
|
||||
// repoAssignment extracts information from URL parameters to retrieve the repository,
|
||||
// and makes sure the context user has at least the read access to the repository.
|
||||
func repoAssignment() macaron.Handler {
|
||||
return func(c *context.APIContext) {
|
||||
username := c.Params(":username")
|
||||
reponame := c.Params(":reponame")
|
||||
|
||||
var err error
|
||||
var owner *db.User
|
||||
|
||||
// Check if the context user is the repository owner.
|
||||
if c.IsLogged && c.User.LowerName == strings.ToLower(username) {
|
||||
owner = c.User
|
||||
} else {
|
||||
owner, err = db.GetUserByName(username)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Repo.Owner = owner
|
||||
|
||||
r, err := db.GetRepositoryByName(owner.ID, reponame)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
|
||||
return
|
||||
} else if err = r.GetOwner(); err != nil {
|
||||
c.ServerError("GetOwner", err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.IsTokenAuth && c.User.IsAdmin {
|
||||
c.Repo.AccessMode = db.ACCESS_MODE_OWNER
|
||||
} else {
|
||||
mode, err := db.UserAccessMode(c.UserID(), r)
|
||||
if err != nil {
|
||||
c.ServerError("UserAccessMode", err)
|
||||
return
|
||||
}
|
||||
c.Repo.AccessMode = mode
|
||||
}
|
||||
|
||||
if !c.Repo.HasAccess() {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
c.Repo.Repository = r
|
||||
}
|
||||
}
|
||||
|
||||
// orgAssignment extracts information from URL parameters to retrieve the organization or team.
|
||||
func orgAssignment(args ...bool) macaron.Handler {
|
||||
var (
|
||||
assignOrg bool
|
||||
assignTeam bool
|
||||
)
|
||||
if len(args) > 0 {
|
||||
assignOrg = args[0]
|
||||
}
|
||||
if len(args) > 1 {
|
||||
assignTeam = args[1]
|
||||
}
|
||||
return func(c *context.APIContext) {
|
||||
c.Org = new(context.APIOrganization)
|
||||
|
||||
var err error
|
||||
if assignOrg {
|
||||
c.Org.Organization, err = db.GetUserByName(c.Params(":orgname"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if assignTeam {
|
||||
c.Org.Team, err = db.GetTeamByID(c.ParamsInt64(":teamid"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetTeamByID", errors.IsTeamNotExist, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqToken makes sure the context user is authorized via access token.
|
||||
func reqToken() macaron.Handler {
|
||||
return func(c *context.Context) {
|
||||
if !c.IsTokenAuth {
|
||||
c.Error(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqBasicAuth makes sure the context user is authorized via HTTP Basic Auth.
|
||||
func reqBasicAuth() macaron.Handler {
|
||||
return func(c *context.Context) {
|
||||
if !c.IsBasicAuth {
|
||||
c.Error(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqAdmin makes sure the context user is a site admin.
|
||||
func reqAdmin() macaron.Handler {
|
||||
return func(c *context.Context) {
|
||||
if !c.IsLogged || !c.User.IsAdmin {
|
||||
c.Error(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqRepoWriter makes sure the context user has at least write access to the repository.
|
||||
func reqRepoWriter() macaron.Handler {
|
||||
return func(c *context.Context) {
|
||||
if !c.Repo.IsWriter() {
|
||||
c.Error(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqRepoWriter makes sure the context user has at least admin access to the repository.
|
||||
func reqRepoAdmin() macaron.Handler {
|
||||
return func(c *context.Context) {
|
||||
if !c.Repo.IsAdmin() {
|
||||
c.Error(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustEnableIssues(c *context.APIContext) {
|
||||
if !c.Repo.Repository.EnableIssues || c.Repo.Repository.EnableExternalTracker {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes registers all route in API v1 to the web application.
|
||||
// FIXME: custom form error response
|
||||
func RegisterRoutes(m *macaron.Macaron) {
|
||||
bind := binding.Bind
|
||||
|
||||
m.Group("/v1", func() {
|
||||
// Handle preflight OPTIONS request
|
||||
m.Options("/*", func() {})
|
||||
|
||||
// Miscellaneous
|
||||
m.Post("/markdown", bind(api.MarkdownOption{}), misc2.Markdown)
|
||||
m.Post("/markdown/raw", misc2.MarkdownRaw)
|
||||
|
||||
// Users
|
||||
m.Group("/users", func() {
|
||||
m.Get("/search", user2.Search)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Get("", user2.GetInfo)
|
||||
|
||||
m.Group("/tokens", func() {
|
||||
m.Combo("").
|
||||
Get(user2.ListAccessTokens).
|
||||
Post(bind(api.CreateAccessTokenOption{}), user2.CreateAccessToken)
|
||||
}, reqBasicAuth())
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/users", func() {
|
||||
m.Group("/:username", func() {
|
||||
m.Get("/keys", user2.ListPublicKeys)
|
||||
|
||||
m.Get("/followers", user2.ListFollowers)
|
||||
m.Group("/following", func() {
|
||||
m.Get("", user2.ListFollowing)
|
||||
m.Get("/:target", user2.CheckFollowing)
|
||||
})
|
||||
})
|
||||
}, reqToken())
|
||||
|
||||
m.Group("/user", func() {
|
||||
m.Get("", user2.GetAuthenticatedUser)
|
||||
m.Combo("/emails").
|
||||
Get(user2.ListEmails).
|
||||
Post(bind(api.CreateEmailOption{}), user2.AddEmail).
|
||||
Delete(bind(api.CreateEmailOption{}), user2.DeleteEmail)
|
||||
|
||||
m.Get("/followers", user2.ListMyFollowers)
|
||||
m.Group("/following", func() {
|
||||
m.Get("", user2.ListMyFollowing)
|
||||
m.Combo("/:username").
|
||||
Get(user2.CheckMyFollowing).
|
||||
Put(user2.Follow).
|
||||
Delete(user2.Unfollow)
|
||||
})
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").
|
||||
Get(user2.ListMyPublicKeys).
|
||||
Post(bind(api.CreateKeyOption{}), user2.CreatePublicKey)
|
||||
m.Combo("/:id").
|
||||
Get(user2.GetPublicKey).
|
||||
Delete(user2.DeletePublicKey)
|
||||
})
|
||||
|
||||
m.Get("/issues", repo2.ListUserIssues)
|
||||
}, reqToken())
|
||||
|
||||
// Repositories
|
||||
m.Get("/users/:username/repos", reqToken(), repo2.ListUserRepositories)
|
||||
m.Get("/orgs/:org/repos", reqToken(), repo2.ListOrgRepositories)
|
||||
m.Combo("/user/repos", reqToken()).
|
||||
Get(repo2.ListMyRepos).
|
||||
Post(bind(api.CreateRepoOption{}), repo2.Create)
|
||||
m.Post("/org/:org/repos", reqToken(), bind(api.CreateRepoOption{}), repo2.CreateOrgRepo)
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Get("/search", repo2.Search)
|
||||
|
||||
m.Get("/:username/:reponame", repoAssignment(), repo2.Get)
|
||||
})
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Post("/migrate", bind(form.MigrateRepo{}), repo2.Migrate)
|
||||
m.Delete("/:username/:reponame", repoAssignment(), repo2.Delete)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Group("/hooks", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListHooks).
|
||||
Post(bind(api.CreateHookOption{}), repo2.CreateHook)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditHookOption{}), repo2.EditHook).
|
||||
Delete(repo2.DeleteHook)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Group("/collaborators", func() {
|
||||
m.Get("", repo2.ListCollaborators)
|
||||
m.Combo("/:collaborator").
|
||||
Get(repo2.IsCollaborator).
|
||||
Put(bind(api.AddCollaboratorOption{}), repo2.AddCollaborator).
|
||||
Delete(repo2.DeleteCollaborator)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Get("/raw/*", context.RepoRef(), repo2.GetRawFile)
|
||||
m.Get("/archive/*", repo2.GetArchive)
|
||||
m.Get("/forks", repo2.ListForks)
|
||||
m.Group("/branches", func() {
|
||||
m.Get("", repo2.ListBranches)
|
||||
m.Get("/*", repo2.GetBranch)
|
||||
})
|
||||
m.Group("/commits", func() {
|
||||
m.Get("/:sha", repo2.GetSingleCommit)
|
||||
m.Get("/*", repo2.GetReferenceSHA)
|
||||
})
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListDeployKeys).
|
||||
Post(bind(api.CreateKeyOption{}), repo2.CreateDeployKey)
|
||||
m.Combo("/:id").
|
||||
Get(repo2.GetDeployKey).
|
||||
Delete(repo2.DeleteDeploykey)
|
||||
}, reqRepoAdmin())
|
||||
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListIssues).
|
||||
Post(bind(api.CreateIssueOption{}), repo2.CreateIssue)
|
||||
m.Group("/comments", func() {
|
||||
m.Get("", repo2.ListRepoIssueComments)
|
||||
m.Patch("/:id", bind(api.EditIssueCommentOption{}), repo2.EditIssueComment)
|
||||
})
|
||||
m.Group("/:index", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.GetIssue).
|
||||
Patch(bind(api.EditIssueOption{}), repo2.EditIssue)
|
||||
|
||||
m.Group("/comments", func() {
|
||||
m.Combo("").
|
||||
Get(repo2.ListIssueComments).
|
||||
Post(bind(api.CreateIssueCommentOption{}), repo2.CreateIssueComment)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditIssueCommentOption{}), repo2.EditIssueComment).
|
||||
Delete(repo2.DeleteIssueComment)
|
||||
})
|
||||
|
||||
m.Get("/labels", repo2.ListIssueLabels)
|
||||
m.Group("/labels", func() {
|
||||
m.Combo("").
|
||||
Post(bind(api.IssueLabelsOption{}), repo2.AddIssueLabels).
|
||||
Put(bind(api.IssueLabelsOption{}), repo2.ReplaceIssueLabels).
|
||||
Delete(repo2.ClearIssueLabels)
|
||||
m.Delete("/:id", repo2.DeleteIssueLabel)
|
||||
}, reqRepoWriter())
|
||||
})
|
||||
}, mustEnableIssues)
|
||||
|
||||
m.Group("/labels", func() {
|
||||
m.Get("", repo2.ListLabels)
|
||||
m.Get("/:id", repo2.GetLabel)
|
||||
})
|
||||
m.Group("/labels", func() {
|
||||
m.Post("", bind(api.CreateLabelOption{}), repo2.CreateLabel)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditLabelOption{}), repo2.EditLabel).
|
||||
Delete(repo2.DeleteLabel)
|
||||
}, reqRepoWriter())
|
||||
|
||||
m.Group("/milestones", func() {
|
||||
m.Get("", repo2.ListMilestones)
|
||||
m.Get("/:id", repo2.GetMilestone)
|
||||
})
|
||||
m.Group("/milestones", func() {
|
||||
m.Post("", bind(api.CreateMilestoneOption{}), repo2.CreateMilestone)
|
||||
m.Combo("/:id").
|
||||
Patch(bind(api.EditMilestoneOption{}), repo2.EditMilestone).
|
||||
Delete(repo2.DeleteMilestone)
|
||||
}, reqRepoWriter())
|
||||
|
||||
m.Patch("/issue-tracker", reqRepoWriter(), bind(api.EditIssueTrackerOption{}), repo2.IssueTracker)
|
||||
m.Post("/mirror-sync", reqRepoWriter(), repo2.MirrorSync)
|
||||
m.Get("/editorconfig/:filename", context.RepoRef(), repo2.GetEditorconfig)
|
||||
}, repoAssignment())
|
||||
}, reqToken())
|
||||
|
||||
m.Get("/issues", reqToken(), repo2.ListUserIssues)
|
||||
|
||||
// Organizations
|
||||
m.Combo("/user/orgs", reqToken()).
|
||||
Get(org2.ListMyOrgs).
|
||||
Post(bind(api.CreateOrgOption{}), org2.CreateMyOrg)
|
||||
|
||||
m.Get("/users/:username/orgs", org2.ListUserOrgs)
|
||||
m.Group("/orgs/:orgname", func() {
|
||||
m.Combo("").
|
||||
Get(org2.Get).
|
||||
Patch(bind(api.EditOrgOption{}), org2.Edit)
|
||||
m.Get("/teams", org2.ListTeams)
|
||||
}, orgAssignment(true))
|
||||
|
||||
m.Group("/admin", func() {
|
||||
m.Group("/users", func() {
|
||||
m.Post("", bind(api.CreateUserOption{}), admin2.CreateUser)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
m.Combo("").
|
||||
Patch(bind(api.EditUserOption{}), admin2.EditUser).
|
||||
Delete(admin2.DeleteUser)
|
||||
m.Post("/keys", bind(api.CreateKeyOption{}), admin2.CreatePublicKey)
|
||||
m.Post("/orgs", bind(api.CreateOrgOption{}), admin2.CreateOrg)
|
||||
m.Post("/repos", bind(api.CreateRepoOption{}), admin2.CreateRepo)
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/orgs/:orgname", func() {
|
||||
m.Group("/teams", func() {
|
||||
m.Post("", orgAssignment(true), bind(api.CreateTeamOption{}), admin2.CreateTeam)
|
||||
})
|
||||
})
|
||||
|
||||
m.Group("/teams", func() {
|
||||
m.Group("/:teamid", func() {
|
||||
m.Combo("/members/:username").
|
||||
Put(admin2.AddTeamMember).
|
||||
Delete(admin2.RemoveTeamMember)
|
||||
m.Combo("/repos/:reponame").
|
||||
Put(admin2.AddTeamRepository).
|
||||
Delete(admin2.RemoveTeamRepository)
|
||||
}, orgAssignment(false, true))
|
||||
})
|
||||
}, reqAdmin())
|
||||
|
||||
m.Any("/*", func(c *context.Context) {
|
||||
c.NotFound()
|
||||
})
|
||||
}, context.APIContexter())
|
||||
}
|
||||
127
internal/route/api/v1/convert/convert.go
Normal file
127
internal/route/api/v1/convert/convert.go
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
|
||||
"github.com/gogs/git-module"
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func ToEmail(email *db.EmailAddress) *api.Email {
|
||||
return &api.Email{
|
||||
Email: email.Email,
|
||||
Verified: email.IsActivated,
|
||||
Primary: email.IsPrimary,
|
||||
}
|
||||
}
|
||||
|
||||
func ToBranch(b *db.Branch, c *git.Commit) *api.Branch {
|
||||
return &api.Branch{
|
||||
Name: b.Name,
|
||||
Commit: ToCommit(c),
|
||||
}
|
||||
}
|
||||
|
||||
func ToCommit(c *git.Commit) *api.PayloadCommit {
|
||||
authorUsername := ""
|
||||
author, err := db.GetUserByEmail(c.Author.Email)
|
||||
if err == nil {
|
||||
authorUsername = author.Name
|
||||
}
|
||||
committerUsername := ""
|
||||
committer, err := db.GetUserByEmail(c.Committer.Email)
|
||||
if err == nil {
|
||||
committerUsername = committer.Name
|
||||
}
|
||||
return &api.PayloadCommit{
|
||||
ID: c.ID.String(),
|
||||
Message: c.Message(),
|
||||
URL: "Not implemented",
|
||||
Author: &api.PayloadUser{
|
||||
Name: c.Author.Name,
|
||||
Email: c.Author.Email,
|
||||
UserName: authorUsername,
|
||||
},
|
||||
Committer: &api.PayloadUser{
|
||||
Name: c.Committer.Name,
|
||||
Email: c.Committer.Email,
|
||||
UserName: committerUsername,
|
||||
},
|
||||
Timestamp: c.Author.When,
|
||||
}
|
||||
}
|
||||
|
||||
func ToPublicKey(apiLink string, key *db.PublicKey) *api.PublicKey {
|
||||
return &api.PublicKey{
|
||||
ID: key.ID,
|
||||
Key: key.Content,
|
||||
URL: apiLink + com.ToStr(key.ID),
|
||||
Title: key.Name,
|
||||
Created: key.Created,
|
||||
}
|
||||
}
|
||||
|
||||
func ToHook(repoLink string, w *db.Webhook) *api.Hook {
|
||||
config := map[string]string{
|
||||
"url": w.URL,
|
||||
"content_type": w.ContentType.Name(),
|
||||
}
|
||||
if w.HookTaskType == db.SLACK {
|
||||
s := w.GetSlackHook()
|
||||
config["channel"] = s.Channel
|
||||
config["username"] = s.Username
|
||||
config["icon_url"] = s.IconURL
|
||||
config["color"] = s.Color
|
||||
}
|
||||
|
||||
return &api.Hook{
|
||||
ID: w.ID,
|
||||
Type: w.HookTaskType.Name(),
|
||||
URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID),
|
||||
Active: w.IsActive,
|
||||
Config: config,
|
||||
Events: w.EventsArray(),
|
||||
Updated: w.Updated,
|
||||
Created: w.Created,
|
||||
}
|
||||
}
|
||||
|
||||
func ToDeployKey(apiLink string, key *db.DeployKey) *api.DeployKey {
|
||||
return &api.DeployKey{
|
||||
ID: key.ID,
|
||||
Key: key.Content,
|
||||
URL: apiLink + com.ToStr(key.ID),
|
||||
Title: key.Name,
|
||||
Created: key.Created,
|
||||
ReadOnly: true, // All deploy keys are read-only.
|
||||
}
|
||||
}
|
||||
|
||||
func ToOrganization(org *db.User) *api.Organization {
|
||||
return &api.Organization{
|
||||
ID: org.ID,
|
||||
AvatarUrl: org.AvatarLink(),
|
||||
UserName: org.Name,
|
||||
FullName: org.FullName,
|
||||
Description: org.Description,
|
||||
Website: org.Website,
|
||||
Location: org.Location,
|
||||
}
|
||||
}
|
||||
|
||||
func ToTeam(team *db.Team) *api.Team {
|
||||
return &api.Team{
|
||||
ID: team.ID,
|
||||
Name: team.Name,
|
||||
Description: team.Description,
|
||||
Permission: team.Authorize.String(),
|
||||
}
|
||||
}
|
||||
19
internal/route/api/v1/convert/utils.go
Normal file
19
internal/route/api/v1/convert/utils.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
// ToCorrectPageSize makes sure page size is in allowed range.
|
||||
func ToCorrectPageSize(size int) int {
|
||||
if size <= 0 {
|
||||
size = 10
|
||||
} else if size > setting.API.MaxResponseItems {
|
||||
size = setting.API.MaxResponseItems
|
||||
}
|
||||
return size
|
||||
}
|
||||
42
internal/route/api/v1/misc/markdown.go
Normal file
42
internal/route/api/v1/misc/markdown.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package misc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/markup"
|
||||
)
|
||||
|
||||
func Markdown(c *context.APIContext, form api.MarkdownOption) {
|
||||
if c.HasApiError() {
|
||||
c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg())
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Text) == 0 {
|
||||
c.Write([]byte(""))
|
||||
return
|
||||
}
|
||||
|
||||
switch form.Mode {
|
||||
case "gfm":
|
||||
c.Write(markup.Markdown([]byte(form.Text), form.Context, nil))
|
||||
default:
|
||||
c.Write(markup.RawMarkdown([]byte(form.Text), ""))
|
||||
}
|
||||
}
|
||||
|
||||
func MarkdownRaw(c *context.APIContext) {
|
||||
body, err := c.Req.Body().Bytes()
|
||||
if err != nil {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
return
|
||||
}
|
||||
c.Write(markup.RawMarkdown(body, ""))
|
||||
}
|
||||
96
internal/route/api/v1/org/org.go
Normal file
96
internal/route/api/v1/org/org.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
user2 "gogs.io/gogs/internal/route/api/v1/user"
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user *db.User) {
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
org := &db.User{
|
||||
Name: apiForm.UserName,
|
||||
FullName: apiForm.FullName,
|
||||
Description: apiForm.Description,
|
||||
Website: apiForm.Website,
|
||||
Location: apiForm.Location,
|
||||
IsActive: true,
|
||||
Type: db.USER_TYPE_ORGANIZATION,
|
||||
}
|
||||
if err := db.CreateOrganization(org, user); err != nil {
|
||||
if db.IsErrUserAlreadyExist(err) ||
|
||||
db.IsErrNameReserved(err) ||
|
||||
db.IsErrNamePatternNotAllowed(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("CreateOrganization", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(201, convert2.ToOrganization(org))
|
||||
}
|
||||
|
||||
func listUserOrgs(c *context.APIContext, u *db.User, all bool) {
|
||||
if err := u.GetOrganizations(all); err != nil {
|
||||
c.ServerError("GetOrganizations", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiOrgs := make([]*api.Organization, len(u.Orgs))
|
||||
for i := range u.Orgs {
|
||||
apiOrgs[i] = convert2.ToOrganization(u.Orgs[i])
|
||||
}
|
||||
c.JSONSuccess(&apiOrgs)
|
||||
}
|
||||
|
||||
func ListMyOrgs(c *context.APIContext) {
|
||||
listUserOrgs(c, c.User, true)
|
||||
}
|
||||
|
||||
func CreateMyOrg(c *context.APIContext, apiForm api.CreateOrgOption) {
|
||||
CreateOrgForUser(c, apiForm, c.User)
|
||||
}
|
||||
|
||||
func ListUserOrgs(c *context.APIContext) {
|
||||
u := user2.GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
listUserOrgs(c, u, false)
|
||||
}
|
||||
|
||||
func Get(c *context.APIContext) {
|
||||
c.JSONSuccess(convert2.ToOrganization(c.Org.Organization))
|
||||
}
|
||||
|
||||
func Edit(c *context.APIContext, form api.EditOrgOption) {
|
||||
org := c.Org.Organization
|
||||
if !org.IsOwnedBy(c.User.ID) {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
org.FullName = form.FullName
|
||||
org.Description = form.Description
|
||||
org.Website = form.Website
|
||||
org.Location = form.Location
|
||||
if err := db.UpdateUser(org); err != nil {
|
||||
c.ServerError("UpdateUser", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSONSuccess(convert2.ToOrganization(org))
|
||||
}
|
||||
26
internal/route/api/v1/org/team.go
Normal file
26
internal/route/api/v1/org/team.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
)
|
||||
|
||||
func ListTeams(c *context.APIContext) {
|
||||
org := c.Org.Organization
|
||||
if err := org.GetTeams(); err != nil {
|
||||
c.Error(500, "GetTeams", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiTeams := make([]*api.Team, len(org.Teams))
|
||||
for i := range org.Teams {
|
||||
apiTeams[i] = convert2.ToTeam(org.Teams[i])
|
||||
}
|
||||
c.JSON(200, apiTeams)
|
||||
}
|
||||
55
internal/route/api/v1/repo/branch.go
Normal file
55
internal/route/api/v1/repo/branch.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories#get-branch
|
||||
func GetBranch(c *context.APIContext) {
|
||||
branch, err := c.Repo.Repository.GetBranch(c.Params("*"))
|
||||
if err != nil {
|
||||
if errors.IsErrBranchNotExist(err) {
|
||||
c.Error(404, "GetBranch", err)
|
||||
} else {
|
||||
c.Error(500, "GetBranch", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
commit, err := branch.GetCommit()
|
||||
if err != nil {
|
||||
c.Error(500, "GetCommit", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, convert2.ToBranch(branch, commit))
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories#list-branches
|
||||
func ListBranches(c *context.APIContext) {
|
||||
branches, err := c.Repo.Repository.GetBranches()
|
||||
if err != nil {
|
||||
c.Error(500, "GetBranches", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiBranches := make([]*api.Branch, len(branches))
|
||||
for i := range branches {
|
||||
commit, err := branches[i].GetCommit()
|
||||
if err != nil {
|
||||
c.Error(500, "GetCommit", err)
|
||||
return
|
||||
}
|
||||
apiBranches[i] = convert2.ToBranch(branches[i], commit)
|
||||
}
|
||||
|
||||
c.JSON(200, &apiBranches)
|
||||
}
|
||||
90
internal/route/api/v1/repo/collaborators.go
Normal file
90
internal/route/api/v1/repo/collaborators.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
func ListCollaborators(c *context.APIContext) {
|
||||
collaborators, err := c.Repo.Repository.GetCollaborators()
|
||||
if err != nil {
|
||||
c.ServerError("GetCollaborators", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiCollaborators := make([]*api.Collaborator, len(collaborators))
|
||||
for i := range collaborators {
|
||||
apiCollaborators[i] = collaborators[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiCollaborators)
|
||||
}
|
||||
|
||||
func AddCollaborator(c *context.APIContext, form api.AddCollaboratorOption) {
|
||||
collaborator, err := db.GetUserByName(c.Params(":collaborator"))
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(422, "", err)
|
||||
} else {
|
||||
c.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.Repo.Repository.AddCollaborator(collaborator); err != nil {
|
||||
c.Error(500, "AddCollaborator", err)
|
||||
return
|
||||
}
|
||||
|
||||
if form.Permission != nil {
|
||||
if err := c.Repo.Repository.ChangeCollaborationAccessMode(collaborator.ID, db.ParseAccessMode(*form.Permission)); err != nil {
|
||||
c.Error(500, "ChangeCollaborationAccessMode", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Status(204)
|
||||
}
|
||||
|
||||
func IsCollaborator(c *context.APIContext) {
|
||||
collaborator, err := db.GetUserByName(c.Params(":collaborator"))
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(422, "", err)
|
||||
} else {
|
||||
c.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !c.Repo.Repository.IsCollaborator(collaborator.ID) {
|
||||
c.Status(404)
|
||||
} else {
|
||||
c.Status(204)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteCollaborator(c *context.APIContext) {
|
||||
collaborator, err := db.GetUserByName(c.Params(":collaborator"))
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(422, "", err)
|
||||
} else {
|
||||
c.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.Repo.Repository.DeleteCollaboration(collaborator.ID); err != nil {
|
||||
c.Error(500, "DeleteCollaboration", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(204)
|
||||
}
|
||||
138
internal/route/api/v1/repo/commits.go
Normal file
138
internal/route/api/v1/repo/commits.go
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright 2018 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogs/git-module"
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func GetSingleCommit(c *context.APIContext) {
|
||||
if strings.Contains(c.Req.Header.Get("Accept"), api.MediaApplicationSHA) {
|
||||
c.SetParams("*", c.Params(":sha"))
|
||||
GetReferenceSHA(c)
|
||||
return
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(c.Repo.Repository.RepoPath())
|
||||
if err != nil {
|
||||
c.ServerError("OpenRepository", err)
|
||||
return
|
||||
}
|
||||
commit, err := gitRepo.GetCommit(c.Params(":sha"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetCommit", git.IsErrNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Retrieve author and committer information
|
||||
var apiAuthor, apiCommitter *api.User
|
||||
author, err := db.GetUserByEmail(commit.Author.Email)
|
||||
if err != nil && !errors.IsUserNotExist(err) {
|
||||
c.ServerError("Get user by author email", err)
|
||||
return
|
||||
} else if err == nil {
|
||||
apiAuthor = author.APIFormat()
|
||||
}
|
||||
// Save one query if the author is also the committer
|
||||
if commit.Committer.Email == commit.Author.Email {
|
||||
apiCommitter = apiAuthor
|
||||
} else {
|
||||
committer, err := db.GetUserByEmail(commit.Committer.Email)
|
||||
if err != nil && !errors.IsUserNotExist(err) {
|
||||
c.ServerError("Get user by committer email", err)
|
||||
return
|
||||
} else if err == nil {
|
||||
apiCommitter = committer.APIFormat()
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve parent(s) of the commit
|
||||
apiParents := make([]*api.CommitMeta, commit.ParentCount())
|
||||
for i := 0; i < commit.ParentCount(); i++ {
|
||||
sha, _ := commit.ParentID(i)
|
||||
apiParents[i] = &api.CommitMeta{
|
||||
URL: c.BaseURL + "/repos/" + c.Repo.Repository.FullName() + "/commits/" + sha.String(),
|
||||
SHA: sha.String(),
|
||||
}
|
||||
}
|
||||
|
||||
c.JSONSuccess(&api.Commit{
|
||||
CommitMeta: &api.CommitMeta{
|
||||
URL: setting.AppURL + c.Link[1:],
|
||||
SHA: commit.ID.String(),
|
||||
},
|
||||
HTMLURL: c.Repo.Repository.HTMLURL() + "/commits/" + commit.ID.String(),
|
||||
RepoCommit: &api.RepoCommit{
|
||||
URL: setting.AppURL + c.Link[1:],
|
||||
Author: &api.CommitUser{
|
||||
Name: commit.Author.Name,
|
||||
Email: commit.Author.Email,
|
||||
Date: commit.Author.When.Format(time.RFC3339),
|
||||
},
|
||||
Committer: &api.CommitUser{
|
||||
Name: commit.Committer.Name,
|
||||
Email: commit.Committer.Email,
|
||||
Date: commit.Committer.When.Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.Summary(),
|
||||
Tree: &api.CommitMeta{
|
||||
URL: c.BaseURL + "/repos/" + c.Repo.Repository.FullName() + "/tree/" + commit.ID.String(),
|
||||
SHA: commit.ID.String(),
|
||||
},
|
||||
},
|
||||
Author: apiAuthor,
|
||||
Committer: apiCommitter,
|
||||
Parents: apiParents,
|
||||
})
|
||||
}
|
||||
|
||||
func GetReferenceSHA(c *context.APIContext) {
|
||||
gitRepo, err := git.OpenRepository(c.Repo.Repository.RepoPath())
|
||||
if err != nil {
|
||||
c.ServerError("OpenRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
ref := c.Params("*")
|
||||
refType := 0 // 0-undetermined, 1-branch, 2-tag
|
||||
if strings.HasPrefix(ref, git.BRANCH_PREFIX) {
|
||||
ref = strings.TrimPrefix(ref, git.BRANCH_PREFIX)
|
||||
refType = 1
|
||||
} else if strings.HasPrefix(ref, git.TAG_PREFIX) {
|
||||
ref = strings.TrimPrefix(ref, git.TAG_PREFIX)
|
||||
refType = 2
|
||||
} else {
|
||||
if gitRepo.IsBranchExist(ref) {
|
||||
refType = 1
|
||||
} else if gitRepo.IsTagExist(ref) {
|
||||
refType = 2
|
||||
} else {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var sha string
|
||||
if refType == 1 {
|
||||
sha, err = gitRepo.GetBranchCommitID(ref)
|
||||
} else if refType == 2 {
|
||||
sha, err = gitRepo.GetTagCommitID(ref)
|
||||
}
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("get reference commit ID", git.IsErrNotExist, err)
|
||||
return
|
||||
}
|
||||
c.PlainText(http.StatusOK, []byte(sha))
|
||||
}
|
||||
62
internal/route/api/v1/repo/file.go
Normal file
62
internal/route/api/v1/repo/file.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/gogs/git-module"
|
||||
repo2 "gogs.io/gogs/internal/route/repo"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func GetRawFile(c *context.APIContext) {
|
||||
if !c.Repo.HasAccess() {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
if c.Repo.Repository.IsBare {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
blob, err := c.Repo.Commit.GetBlobByPath(c.Repo.TreePath)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetBlobByPath", git.IsErrNotExist, err)
|
||||
return
|
||||
}
|
||||
if err = repo2.ServeBlob(c.Context, blob); err != nil {
|
||||
c.ServerError("ServeBlob", err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetArchive(c *context.APIContext) {
|
||||
repoPath := db.RepoPath(c.Params(":username"), c.Params(":reponame"))
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
c.ServerError("OpenRepository", err)
|
||||
return
|
||||
}
|
||||
c.Repo.GitRepo = gitRepo
|
||||
|
||||
repo2.Download(c.Context)
|
||||
}
|
||||
|
||||
func GetEditorconfig(c *context.APIContext) {
|
||||
ec, err := c.Repo.GetEditorconfig()
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetEditorconfig", git.IsErrNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
fileName := c.Params("filename")
|
||||
def := ec.GetDefinitionForFilename(fileName)
|
||||
if def == nil {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
c.JSONSuccess(def)
|
||||
}
|
||||
185
internal/route/api/v1/repo/hook.go
Normal file
185
internal/route/api/v1/repo/hook.go
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/json-iterator/go"
|
||||
"github.com/unknwon/com"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories#list-hooks
|
||||
func ListHooks(c *context.APIContext) {
|
||||
hooks, err := db.GetWebhooksByRepoID(c.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
c.Error(500, "GetWebhooksByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiHooks := make([]*api.Hook, len(hooks))
|
||||
for i := range hooks {
|
||||
apiHooks[i] = convert2.ToHook(c.Repo.RepoLink, hooks[i])
|
||||
}
|
||||
c.JSON(200, &apiHooks)
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories#create-a-hook
|
||||
func CreateHook(c *context.APIContext, form api.CreateHookOption) {
|
||||
if !db.IsValidHookTaskType(form.Type) {
|
||||
c.Error(422, "", "Invalid hook type")
|
||||
return
|
||||
}
|
||||
for _, name := range []string{"url", "content_type"} {
|
||||
if _, ok := form.Config[name]; !ok {
|
||||
c.Error(422, "", "Missing config option: "+name)
|
||||
return
|
||||
}
|
||||
}
|
||||
if !db.IsValidHookContentType(form.Config["content_type"]) {
|
||||
c.Error(422, "", "Invalid content type")
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Events) == 0 {
|
||||
form.Events = []string{"push"}
|
||||
}
|
||||
w := &db.Webhook{
|
||||
RepoID: c.Repo.Repository.ID,
|
||||
URL: form.Config["url"],
|
||||
ContentType: db.ToHookContentType(form.Config["content_type"]),
|
||||
Secret: form.Config["secret"],
|
||||
HookEvent: &db.HookEvent{
|
||||
ChooseEvents: true,
|
||||
HookEvents: db.HookEvents{
|
||||
Create: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_CREATE)),
|
||||
Delete: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_DELETE)),
|
||||
Fork: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_FORK)),
|
||||
Push: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PUSH)),
|
||||
Issues: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_ISSUES)),
|
||||
IssueComment: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_ISSUE_COMMENT)),
|
||||
PullRequest: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PULL_REQUEST)),
|
||||
Release: com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_RELEASE)),
|
||||
},
|
||||
},
|
||||
IsActive: form.Active,
|
||||
HookTaskType: db.ToHookTaskType(form.Type),
|
||||
}
|
||||
if w.HookTaskType == db.SLACK {
|
||||
channel, ok := form.Config["channel"]
|
||||
if !ok {
|
||||
c.Error(422, "", "Missing config option: channel")
|
||||
return
|
||||
}
|
||||
meta, err := jsoniter.Marshal(&db.SlackMeta{
|
||||
Channel: channel,
|
||||
Username: form.Config["username"],
|
||||
IconURL: form.Config["icon_url"],
|
||||
Color: form.Config["color"],
|
||||
})
|
||||
if err != nil {
|
||||
c.Error(500, "slack: JSON marshal failed", err)
|
||||
return
|
||||
}
|
||||
w.Meta = string(meta)
|
||||
}
|
||||
|
||||
if err := w.UpdateEvent(); err != nil {
|
||||
c.Error(500, "UpdateEvent", err)
|
||||
return
|
||||
} else if err := db.CreateWebhook(w); err != nil {
|
||||
c.Error(500, "CreateWebhook", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(201, convert2.ToHook(c.Repo.RepoLink, w))
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories#edit-a-hook
|
||||
func EditHook(c *context.APIContext, form api.EditHookOption) {
|
||||
w, err := db.GetWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if errors.IsWebhookNotExist(err) {
|
||||
c.Status(404)
|
||||
} else {
|
||||
c.Error(500, "GetWebhookOfRepoByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if form.Config != nil {
|
||||
if url, ok := form.Config["url"]; ok {
|
||||
w.URL = url
|
||||
}
|
||||
if ct, ok := form.Config["content_type"]; ok {
|
||||
if !db.IsValidHookContentType(ct) {
|
||||
c.Error(422, "", "Invalid content type")
|
||||
return
|
||||
}
|
||||
w.ContentType = db.ToHookContentType(ct)
|
||||
}
|
||||
|
||||
if w.HookTaskType == db.SLACK {
|
||||
if channel, ok := form.Config["channel"]; ok {
|
||||
meta, err := jsoniter.Marshal(&db.SlackMeta{
|
||||
Channel: channel,
|
||||
Username: form.Config["username"],
|
||||
IconURL: form.Config["icon_url"],
|
||||
Color: form.Config["color"],
|
||||
})
|
||||
if err != nil {
|
||||
c.Error(500, "slack: JSON marshal failed", err)
|
||||
return
|
||||
}
|
||||
w.Meta = string(meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update events
|
||||
if len(form.Events) == 0 {
|
||||
form.Events = []string{"push"}
|
||||
}
|
||||
w.PushOnly = false
|
||||
w.SendEverything = false
|
||||
w.ChooseEvents = true
|
||||
w.Create = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_CREATE))
|
||||
w.Delete = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_DELETE))
|
||||
w.Fork = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_FORK))
|
||||
w.Push = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PUSH))
|
||||
w.Issues = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_ISSUES))
|
||||
w.IssueComment = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_ISSUE_COMMENT))
|
||||
w.PullRequest = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_PULL_REQUEST))
|
||||
w.Release = com.IsSliceContainsStr(form.Events, string(db.HOOK_EVENT_RELEASE))
|
||||
if err = w.UpdateEvent(); err != nil {
|
||||
c.Error(500, "UpdateEvent", err)
|
||||
return
|
||||
}
|
||||
|
||||
if form.Active != nil {
|
||||
w.IsActive = *form.Active
|
||||
}
|
||||
|
||||
if err := db.UpdateWebhook(w); err != nil {
|
||||
c.Error(500, "UpdateWebhook", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, convert2.ToHook(c.Repo.RepoLink, w))
|
||||
}
|
||||
|
||||
func DeleteHook(c *context.APIContext) {
|
||||
if err := db.DeleteWebhookOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
|
||||
c.Error(500, "DeleteWebhookByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(204)
|
||||
}
|
||||
194
internal/route/api/v1/repo/issue.go
Normal file
194
internal/route/api/v1/repo/issue.go
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func listIssues(c *context.APIContext, opts *db.IssuesOptions) {
|
||||
issues, err := db.Issues(opts)
|
||||
if err != nil {
|
||||
c.ServerError("Issues", err)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := db.IssuesCount(opts)
|
||||
if err != nil {
|
||||
c.ServerError("IssuesCount", err)
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: use IssueList to improve performance.
|
||||
apiIssues := make([]*api.Issue, len(issues))
|
||||
for i := range issues {
|
||||
if err = issues[i].LoadAttributes(); err != nil {
|
||||
c.ServerError("LoadAttributes", err)
|
||||
return
|
||||
}
|
||||
apiIssues[i] = issues[i].APIFormat()
|
||||
}
|
||||
|
||||
c.SetLinkHeader(int(count), setting.UI.IssuePagingNum)
|
||||
c.JSONSuccess(&apiIssues)
|
||||
}
|
||||
|
||||
func ListUserIssues(c *context.APIContext) {
|
||||
opts := db.IssuesOptions{
|
||||
AssigneeID: c.User.ID,
|
||||
Page: c.QueryInt("page"),
|
||||
IsClosed: api.StateType(c.Query("state")) == api.STATE_CLOSED,
|
||||
}
|
||||
|
||||
listIssues(c, &opts)
|
||||
}
|
||||
|
||||
func ListIssues(c *context.APIContext) {
|
||||
opts := db.IssuesOptions{
|
||||
RepoID: c.Repo.Repository.ID,
|
||||
Page: c.QueryInt("page"),
|
||||
IsClosed: api.StateType(c.Query("state")) == api.STATE_CLOSED,
|
||||
}
|
||||
|
||||
listIssues(c, &opts)
|
||||
}
|
||||
|
||||
func GetIssue(c *context.APIContext) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
c.JSONSuccess(issue.APIFormat())
|
||||
}
|
||||
|
||||
func CreateIssue(c *context.APIContext, form api.CreateIssueOption) {
|
||||
issue := &db.Issue{
|
||||
RepoID: c.Repo.Repository.ID,
|
||||
Title: form.Title,
|
||||
PosterID: c.User.ID,
|
||||
Poster: c.User,
|
||||
Content: form.Body,
|
||||
}
|
||||
|
||||
if c.Repo.IsWriter() {
|
||||
if len(form.Assignee) > 0 {
|
||||
assignee, err := db.GetUserByName(form.Assignee)
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", form.Assignee))
|
||||
} else {
|
||||
c.ServerError("GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
issue.AssigneeID = assignee.ID
|
||||
}
|
||||
issue.MilestoneID = form.Milestone
|
||||
} else {
|
||||
form.Labels = nil
|
||||
}
|
||||
|
||||
if err := db.NewIssue(c.Repo.Repository, issue, form.Labels, nil); err != nil {
|
||||
c.ServerError("NewIssue", err)
|
||||
return
|
||||
}
|
||||
|
||||
if form.Closed {
|
||||
if err := issue.ChangeStatus(c.User, c.Repo.Repository, true); err != nil {
|
||||
c.ServerError("ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Refetch from database to assign some automatic values
|
||||
var err error
|
||||
issue, err = db.GetIssueByID(issue.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetIssueByID", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, issue.APIFormat())
|
||||
}
|
||||
|
||||
func EditIssue(c *context.APIContext, form api.EditIssueOption) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !issue.IsPoster(c.User.ID) && !c.Repo.IsWriter() {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Title) > 0 {
|
||||
issue.Title = form.Title
|
||||
}
|
||||
if form.Body != nil {
|
||||
issue.Content = *form.Body
|
||||
}
|
||||
|
||||
if c.Repo.IsWriter() && form.Assignee != nil &&
|
||||
(issue.Assignee == nil || issue.Assignee.LowerName != strings.ToLower(*form.Assignee)) {
|
||||
if len(*form.Assignee) == 0 {
|
||||
issue.AssigneeID = 0
|
||||
} else {
|
||||
assignee, err := db.GetUserByName(*form.Assignee)
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("assignee does not exist: [name: %s]", *form.Assignee))
|
||||
} else {
|
||||
c.ServerError("GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
issue.AssigneeID = assignee.ID
|
||||
}
|
||||
|
||||
if err = db.UpdateIssueUserByAssignee(issue); err != nil {
|
||||
c.ServerError("UpdateIssueUserByAssignee", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if c.Repo.IsWriter() && form.Milestone != nil &&
|
||||
issue.MilestoneID != *form.Milestone {
|
||||
oldMilestoneID := issue.MilestoneID
|
||||
issue.MilestoneID = *form.Milestone
|
||||
if err = db.ChangeMilestoneAssign(c.User, issue, oldMilestoneID); err != nil {
|
||||
c.ServerError("ChangeMilestoneAssign", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = db.UpdateIssue(issue); err != nil {
|
||||
c.ServerError("UpdateIssue", err)
|
||||
return
|
||||
}
|
||||
if form.State != nil {
|
||||
if err = issue.ChangeStatus(c.User, c.Repo.Repository, api.STATE_CLOSED == api.StateType(*form.State)); err != nil {
|
||||
c.ServerError("ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Refetch from database to assign some automatic values
|
||||
issue, err = db.GetIssueByID(issue.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetIssueByID", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, issue.APIFormat())
|
||||
}
|
||||
131
internal/route/api/v1/repo/issue_comment.go
Normal file
131
internal/route/api/v1/repo/issue_comment.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func ListIssueComments(c *context.APIContext) {
|
||||
var since time.Time
|
||||
if len(c.Query("since")) > 0 {
|
||||
var err error
|
||||
since, err = time.Parse(time.RFC3339, c.Query("since"))
|
||||
if err != nil {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// comments,err:=db.GetCommentsByIssueIDSince(, since)
|
||||
issue, err := db.GetRawIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.ServerError("GetRawIssueByIndex", err)
|
||||
return
|
||||
}
|
||||
|
||||
comments, err := db.GetCommentsByIssueIDSince(issue.ID, since.Unix())
|
||||
if err != nil {
|
||||
c.ServerError("GetCommentsByIssueIDSince", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiComments := make([]*api.Comment, len(comments))
|
||||
for i := range comments {
|
||||
apiComments[i] = comments[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiComments)
|
||||
}
|
||||
|
||||
func ListRepoIssueComments(c *context.APIContext) {
|
||||
var since time.Time
|
||||
if len(c.Query("since")) > 0 {
|
||||
var err error
|
||||
since, err = time.Parse(time.RFC3339, c.Query("since"))
|
||||
if err != nil {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
comments, err := db.GetCommentsByRepoIDSince(c.Repo.Repository.ID, since.Unix())
|
||||
if err != nil {
|
||||
c.ServerError("GetCommentsByRepoIDSince", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiComments := make([]*api.Comment, len(comments))
|
||||
for i := range comments {
|
||||
apiComments[i] = comments[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiComments)
|
||||
}
|
||||
|
||||
func CreateIssueComment(c *context.APIContext, form api.CreateIssueCommentOption) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.ServerError("GetIssueByIndex", err)
|
||||
return
|
||||
}
|
||||
|
||||
comment, err := db.CreateIssueComment(c.User, c.Repo.Repository, issue, form.Body, nil)
|
||||
if err != nil {
|
||||
c.ServerError("CreateIssueComment", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, comment.APIFormat())
|
||||
}
|
||||
|
||||
func EditIssueComment(c *context.APIContext, form api.EditIssueCommentOption) {
|
||||
comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.User.ID != comment.PosterID && !c.Repo.IsAdmin() {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
} else if comment.Type != db.COMMENT_TYPE_COMMENT {
|
||||
c.NoContent()
|
||||
return
|
||||
}
|
||||
|
||||
oldContent := comment.Content
|
||||
comment.Content = form.Body
|
||||
if err := db.UpdateComment(c.User, comment, oldContent); err != nil {
|
||||
c.ServerError("UpdateComment", err)
|
||||
return
|
||||
}
|
||||
c.JSONSuccess(comment.APIFormat())
|
||||
}
|
||||
|
||||
func DeleteIssueComment(c *context.APIContext) {
|
||||
comment, err := db.GetCommentByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetCommentByID", db.IsErrCommentNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.User.ID != comment.PosterID && !c.Repo.IsAdmin() {
|
||||
c.Status(http.StatusForbidden)
|
||||
return
|
||||
} else if comment.Type != db.COMMENT_TYPE_COMMENT {
|
||||
c.NoContent()
|
||||
return
|
||||
}
|
||||
|
||||
if err = db.DeleteCommentByID(c.User, comment.ID); err != nil {
|
||||
c.ServerError("DeleteCommentByID", err)
|
||||
return
|
||||
}
|
||||
c.NoContent()
|
||||
}
|
||||
131
internal/route/api/v1/repo/issue_label.go
Normal file
131
internal/route/api/v1/repo/issue_label.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
func ListIssueLabels(c *context.APIContext) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLabels := make([]*api.Label, len(issue.Labels))
|
||||
for i := range issue.Labels {
|
||||
apiLabels[i] = issue.Labels[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiLabels)
|
||||
}
|
||||
|
||||
func AddIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels)
|
||||
if err != nil {
|
||||
c.ServerError("GetLabelsInRepoByIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = issue.AddLabels(c.User, labels); err != nil {
|
||||
c.ServerError("AddLabels", err)
|
||||
return
|
||||
}
|
||||
|
||||
labels, err = db.GetLabelsByIssueID(issue.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetLabelsByIssueID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLabels := make([]*api.Label, len(labels))
|
||||
for i := range labels {
|
||||
apiLabels[i] = issue.Labels[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiLabels)
|
||||
}
|
||||
|
||||
func DeleteIssueLabel(c *context.APIContext) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if db.IsErrLabelNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("GetLabelInRepoByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DeleteIssueLabel(issue, label); err != nil {
|
||||
c.ServerError("DeleteIssueLabel", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func ReplaceIssueLabels(c *context.APIContext, form api.IssueLabelsOption) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
labels, err := db.GetLabelsInRepoByIDs(c.Repo.Repository.ID, form.Labels)
|
||||
if err != nil {
|
||||
c.ServerError("GetLabelsInRepoByIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := issue.ReplaceLabels(labels); err != nil {
|
||||
c.ServerError("ReplaceLabels", err)
|
||||
return
|
||||
}
|
||||
|
||||
labels, err = db.GetLabelsByIssueID(issue.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetLabelsByIssueID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLabels := make([]*api.Label, len(labels))
|
||||
for i := range labels {
|
||||
apiLabels[i] = issue.Labels[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiLabels)
|
||||
}
|
||||
|
||||
func ClearIssueLabels(c *context.APIContext) {
|
||||
issue, err := db.GetIssueByIndex(c.Repo.Repository.ID, c.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := issue.ClearLabels(c.User); err != nil {
|
||||
c.ServerError("ClearLabels", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
114
internal/route/api/v1/repo/key.go
Normal file
114
internal/route/api/v1/repo/key.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func composeDeployKeysAPILink(repoPath string) string {
|
||||
return setting.AppURL + "api/v1/repos/" + repoPath + "/keys/"
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#list-deploy-keys
|
||||
func ListDeployKeys(c *context.APIContext) {
|
||||
keys, err := db.ListDeployKeys(c.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
c.Error(500, "ListDeployKeys", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name)
|
||||
apiKeys := make([]*api.DeployKey, len(keys))
|
||||
for i := range keys {
|
||||
if err = keys[i].GetContent(); err != nil {
|
||||
c.Error(500, "GetContent", err)
|
||||
return
|
||||
}
|
||||
apiKeys[i] = convert2.ToDeployKey(apiLink, keys[i])
|
||||
}
|
||||
|
||||
c.JSON(200, &apiKeys)
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#get-a-deploy-key
|
||||
func GetDeployKey(c *context.APIContext) {
|
||||
key, err := db.GetDeployKeyByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if db.IsErrDeployKeyNotExist(err) {
|
||||
c.Status(404)
|
||||
} else {
|
||||
c.Error(500, "GetDeployKeyByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err = key.GetContent(); err != nil {
|
||||
c.Error(500, "GetContent", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name)
|
||||
c.JSON(200, convert2.ToDeployKey(apiLink, key))
|
||||
}
|
||||
|
||||
func HandleCheckKeyStringError(c *context.APIContext, err error) {
|
||||
if db.IsErrKeyUnableVerify(err) {
|
||||
c.Error(422, "", "Unable to verify key content")
|
||||
} else {
|
||||
c.Error(422, "", fmt.Errorf("Invalid key content: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
func HandleAddKeyError(c *context.APIContext, err error) {
|
||||
switch {
|
||||
case db.IsErrKeyAlreadyExist(err):
|
||||
c.Error(422, "", "Key content has been used as non-deploy key")
|
||||
case db.IsErrKeyNameAlreadyUsed(err):
|
||||
c.Error(422, "", "Key title has been used")
|
||||
default:
|
||||
c.Error(500, "AddKey", err)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#add-a-new-deploy-key
|
||||
func CreateDeployKey(c *context.APIContext, form api.CreateKeyOption) {
|
||||
content, err := db.CheckPublicKeyString(form.Key)
|
||||
if err != nil {
|
||||
HandleCheckKeyStringError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
key, err := db.AddDeployKey(c.Repo.Repository.ID, form.Title, content)
|
||||
if err != nil {
|
||||
HandleAddKeyError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
key.Content = content
|
||||
apiLink := composeDeployKeysAPILink(c.Repo.Owner.Name + "/" + c.Repo.Repository.Name)
|
||||
c.JSON(201, convert2.ToDeployKey(apiLink, key))
|
||||
}
|
||||
|
||||
// https://github.com/gogs/go-gogs-client/wiki/Repositories-Deploy-Keys#remove-a-deploy-key
|
||||
func DeleteDeploykey(c *context.APIContext) {
|
||||
if err := db.DeleteDeployKey(c.User, c.ParamsInt64(":id")); err != nil {
|
||||
if db.IsErrKeyAccessDenied(err) {
|
||||
c.Error(403, "", "You do not have access to this key")
|
||||
} else {
|
||||
c.Error(500, "DeleteDeployKey", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(204)
|
||||
}
|
||||
89
internal/route/api/v1/repo/label.go
Normal file
89
internal/route/api/v1/repo/label.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func ListLabels(c *context.APIContext) {
|
||||
labels, err := db.GetLabelsByRepoID(c.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetLabelsByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLabels := make([]*api.Label, len(labels))
|
||||
for i := range labels {
|
||||
apiLabels[i] = labels[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiLabels)
|
||||
}
|
||||
|
||||
func GetLabel(c *context.APIContext) {
|
||||
var label *db.Label
|
||||
var err error
|
||||
idStr := c.Params(":id")
|
||||
if id := com.StrTo(idStr).MustInt64(); id > 0 {
|
||||
label, err = db.GetLabelOfRepoByID(c.Repo.Repository.ID, id)
|
||||
} else {
|
||||
label, err = db.GetLabelOfRepoByName(c.Repo.Repository.ID, idStr)
|
||||
}
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetLabel", db.IsErrLabelNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSONSuccess(label.APIFormat())
|
||||
}
|
||||
|
||||
func CreateLabel(c *context.APIContext, form api.CreateLabelOption) {
|
||||
label := &db.Label{
|
||||
Name: form.Name,
|
||||
Color: form.Color,
|
||||
RepoID: c.Repo.Repository.ID,
|
||||
}
|
||||
if err := db.NewLabels(label); err != nil {
|
||||
c.ServerError("NewLabel", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, label.APIFormat())
|
||||
}
|
||||
|
||||
func EditLabel(c *context.APIContext, form api.EditLabelOption) {
|
||||
label, err := db.GetLabelOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetLabelOfRepoByID", db.IsErrLabelNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if form.Name != nil {
|
||||
label.Name = *form.Name
|
||||
}
|
||||
if form.Color != nil {
|
||||
label.Color = *form.Color
|
||||
}
|
||||
if err := db.UpdateLabel(label); err != nil {
|
||||
c.ServerError("UpdateLabel", err)
|
||||
return
|
||||
}
|
||||
c.JSONSuccess(label.APIFormat())
|
||||
}
|
||||
|
||||
func DeleteLabel(c *context.APIContext) {
|
||||
if err := db.DeleteLabel(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
|
||||
c.ServerError("DeleteLabel", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
96
internal/route/api/v1/repo/milestone.go
Normal file
96
internal/route/api/v1/repo/milestone.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func ListMilestones(c *context.APIContext) {
|
||||
milestones, err := db.GetMilestonesByRepoID(c.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetMilestonesByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiMilestones := make([]*api.Milestone, len(milestones))
|
||||
for i := range milestones {
|
||||
apiMilestones[i] = milestones[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiMilestones)
|
||||
}
|
||||
|
||||
func GetMilestone(c *context.APIContext) {
|
||||
milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err)
|
||||
return
|
||||
}
|
||||
c.JSONSuccess(milestone.APIFormat())
|
||||
}
|
||||
|
||||
func CreateMilestone(c *context.APIContext, form api.CreateMilestoneOption) {
|
||||
if form.Deadline == nil {
|
||||
defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local)
|
||||
form.Deadline = &defaultDeadline
|
||||
}
|
||||
|
||||
milestone := &db.Milestone{
|
||||
RepoID: c.Repo.Repository.ID,
|
||||
Name: form.Title,
|
||||
Content: form.Description,
|
||||
Deadline: *form.Deadline,
|
||||
}
|
||||
|
||||
if err := db.NewMilestone(milestone); err != nil {
|
||||
c.ServerError("NewMilestone", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, milestone.APIFormat())
|
||||
}
|
||||
|
||||
func EditMilestone(c *context.APIContext, form api.EditMilestoneOption) {
|
||||
milestone, err := db.GetMilestoneByRepoID(c.Repo.Repository.ID, c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetMilestoneByRepoID", db.IsErrMilestoneNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Title) > 0 {
|
||||
milestone.Name = form.Title
|
||||
}
|
||||
if form.Description != nil {
|
||||
milestone.Content = *form.Description
|
||||
}
|
||||
if form.Deadline != nil && !form.Deadline.IsZero() {
|
||||
milestone.Deadline = *form.Deadline
|
||||
}
|
||||
|
||||
if form.State != nil {
|
||||
if err = milestone.ChangeStatus(api.STATE_CLOSED == api.StateType(*form.State)); err != nil {
|
||||
c.ServerError("ChangeStatus", err)
|
||||
return
|
||||
}
|
||||
} else if err = db.UpdateMilestone(milestone); err != nil {
|
||||
c.ServerError("UpdateMilestone", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSONSuccess(milestone.APIFormat())
|
||||
}
|
||||
|
||||
func DeleteMilestone(c *context.APIContext) {
|
||||
if err := db.DeleteMilestoneOfRepoByID(c.Repo.Repository.ID, c.ParamsInt64(":id")); err != nil {
|
||||
c.ServerError("DeleteMilestoneByRepoID", err)
|
||||
return
|
||||
}
|
||||
c.NoContent()
|
||||
}
|
||||
407
internal/route/api/v1/repo/repo.go
Normal file
407
internal/route/api/v1/repo/repo.go
Normal file
@@ -0,0 +1,407 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/form"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func Search(c *context.APIContext) {
|
||||
opts := &db.SearchRepoOptions{
|
||||
Keyword: path.Base(c.Query("q")),
|
||||
OwnerID: c.QueryInt64("uid"),
|
||||
PageSize: convert2.ToCorrectPageSize(c.QueryInt("limit")),
|
||||
Page: c.QueryInt("page"),
|
||||
}
|
||||
|
||||
// Check visibility.
|
||||
if c.IsLogged && opts.OwnerID > 0 {
|
||||
if c.User.ID == opts.OwnerID {
|
||||
opts.Private = true
|
||||
} else {
|
||||
u, err := db.GetUserByID(opts.OwnerID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
"ok": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if u.IsOrganization() && u.IsOwnedBy(c.User.ID) {
|
||||
opts.Private = true
|
||||
}
|
||||
// FIXME: how about collaborators?
|
||||
}
|
||||
}
|
||||
|
||||
repos, count, err := db.SearchRepositoryByName(opts)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
"ok": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err = db.RepositoryList(repos).LoadAttributes(); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
"ok": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
results := make([]*api.Repository, len(repos))
|
||||
for i := range repos {
|
||||
results[i] = repos[i].APIFormat(nil)
|
||||
}
|
||||
|
||||
c.SetLinkHeader(int(count), opts.PageSize)
|
||||
c.JSONSuccess(map[string]interface{}{
|
||||
"ok": true,
|
||||
"data": results,
|
||||
})
|
||||
}
|
||||
|
||||
func listUserRepositories(c *context.APIContext, username string) {
|
||||
user, err := db.GetUserByName(username)
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Only list public repositories if user requests someone else's repository list,
|
||||
// or an organization isn't a member of.
|
||||
var ownRepos []*db.Repository
|
||||
if user.IsOrganization() {
|
||||
ownRepos, _, err = user.GetUserRepositories(c.User.ID, 1, user.NumRepos)
|
||||
} else {
|
||||
ownRepos, err = db.GetUserRepositories(&db.UserRepoOptions{
|
||||
UserID: user.ID,
|
||||
Private: c.User.ID == user.ID,
|
||||
Page: 1,
|
||||
PageSize: user.NumRepos,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
c.ServerError("GetUserRepositories", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = db.RepositoryList(ownRepos).LoadAttributes(); err != nil {
|
||||
c.ServerError("LoadAttributes(ownRepos)", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Early return for querying other user's repositories
|
||||
if c.User.ID != user.ID {
|
||||
repos := make([]*api.Repository, len(ownRepos))
|
||||
for i := range ownRepos {
|
||||
repos[i] = ownRepos[i].APIFormat(&api.Permission{true, true, true})
|
||||
}
|
||||
c.JSONSuccess(&repos)
|
||||
return
|
||||
}
|
||||
|
||||
accessibleRepos, err := user.GetRepositoryAccesses()
|
||||
if err != nil {
|
||||
c.ServerError("GetRepositoryAccesses", err)
|
||||
return
|
||||
}
|
||||
|
||||
numOwnRepos := len(ownRepos)
|
||||
repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
|
||||
for i := range ownRepos {
|
||||
repos[i] = ownRepos[i].APIFormat(&api.Permission{true, true, true})
|
||||
}
|
||||
|
||||
i := numOwnRepos
|
||||
for repo, access := range accessibleRepos {
|
||||
repos[i] = repo.APIFormat(&api.Permission{
|
||||
Admin: access >= db.ACCESS_MODE_ADMIN,
|
||||
Push: access >= db.ACCESS_MODE_WRITE,
|
||||
Pull: true,
|
||||
})
|
||||
i++
|
||||
}
|
||||
|
||||
c.JSONSuccess(&repos)
|
||||
}
|
||||
|
||||
func ListMyRepos(c *context.APIContext) {
|
||||
listUserRepositories(c, c.User.Name)
|
||||
}
|
||||
|
||||
func ListUserRepositories(c *context.APIContext) {
|
||||
listUserRepositories(c, c.Params(":username"))
|
||||
}
|
||||
|
||||
func ListOrgRepositories(c *context.APIContext) {
|
||||
listUserRepositories(c, c.Params(":org"))
|
||||
}
|
||||
|
||||
func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOption) {
|
||||
repo, err := db.CreateRepository(c.User, owner, db.CreateRepoOptions{
|
||||
Name: opt.Name,
|
||||
Description: opt.Description,
|
||||
Gitignores: opt.Gitignores,
|
||||
License: opt.License,
|
||||
Readme: opt.Readme,
|
||||
IsPrivate: opt.Private,
|
||||
AutoInit: opt.AutoInit,
|
||||
})
|
||||
if err != nil {
|
||||
if db.IsErrRepoAlreadyExist(err) ||
|
||||
db.IsErrNameReserved(err) ||
|
||||
db.IsErrNamePatternNotAllowed(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
if repo != nil {
|
||||
if err = db.DeleteRepository(c.User.ID, repo.ID); err != nil {
|
||||
log.Error(2, "DeleteRepository: %v", err)
|
||||
}
|
||||
}
|
||||
c.ServerError("CreateRepository", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
func Create(c *context.APIContext, opt api.CreateRepoOption) {
|
||||
// Shouldn't reach this condition, but just in case.
|
||||
if c.User.IsOrganization() {
|
||||
c.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization")
|
||||
return
|
||||
}
|
||||
CreateUserRepo(c, c.User, opt)
|
||||
}
|
||||
|
||||
func CreateOrgRepo(c *context.APIContext, opt api.CreateRepoOption) {
|
||||
org, err := db.GetOrgByName(c.Params(":org"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetOrgByName", errors.IsUserNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !org.IsOwnedBy(c.User.ID) {
|
||||
c.Error(http.StatusForbidden, "", "given user is not owner of organization")
|
||||
return
|
||||
}
|
||||
CreateUserRepo(c, org, opt)
|
||||
}
|
||||
|
||||
func Migrate(c *context.APIContext, f form.MigrateRepo) {
|
||||
ctxUser := c.User
|
||||
// Not equal means context user is an organization,
|
||||
// or is another user/organization if current user is admin.
|
||||
if f.Uid != ctxUser.ID {
|
||||
org, err := db.GetUserByID(f.Uid)
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.Error(http.StatusInternalServerError, "GetUserByID", err)
|
||||
}
|
||||
return
|
||||
} else if !org.IsOrganization() && !c.User.IsAdmin {
|
||||
c.Error(http.StatusForbidden, "", "given user is not an organization")
|
||||
return
|
||||
}
|
||||
ctxUser = org
|
||||
}
|
||||
|
||||
if c.HasError() {
|
||||
c.Error(http.StatusUnprocessableEntity, "", c.GetErrMsg())
|
||||
return
|
||||
}
|
||||
|
||||
if ctxUser.IsOrganization() && !c.User.IsAdmin {
|
||||
// Check ownership of organization.
|
||||
if !ctxUser.IsOwnedBy(c.User.ID) {
|
||||
c.Error(http.StatusForbidden, "", "Given user is not owner of organization")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
remoteAddr, err := f.ParseRemoteAddr(c.User)
|
||||
if err != nil {
|
||||
if db.IsErrInvalidCloneAddr(err) {
|
||||
addrErr := err.(db.ErrInvalidCloneAddr)
|
||||
switch {
|
||||
case addrErr.IsURLError:
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
case addrErr.IsPermissionDenied:
|
||||
c.Error(http.StatusUnprocessableEntity, "", "you are not allowed to import local repositories")
|
||||
case addrErr.IsInvalidPath:
|
||||
c.Error(http.StatusUnprocessableEntity, "", "invalid local path, it does not exist or not a directory")
|
||||
default:
|
||||
c.ServerError("ParseRemoteAddr", fmt.Errorf("unknown error type (ErrInvalidCloneAddr): %v", err))
|
||||
}
|
||||
} else {
|
||||
c.ServerError("ParseRemoteAddr", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := db.MigrateRepository(c.User, ctxUser, db.MigrateRepoOptions{
|
||||
Name: f.RepoName,
|
||||
Description: f.Description,
|
||||
IsPrivate: f.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: f.Mirror,
|
||||
RemoteAddr: remoteAddr,
|
||||
})
|
||||
if err != nil {
|
||||
if repo != nil {
|
||||
if errDelete := db.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
|
||||
log.Error(2, "DeleteRepository: %v", errDelete)
|
||||
}
|
||||
}
|
||||
|
||||
if errors.IsReachLimitOfRepo(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("MigrateRepository", errors.New(db.HandleMirrorCredentials(err.Error(), true)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, f.RepoName)
|
||||
c.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
// FIXME: inject in the handler chain
|
||||
func parseOwnerAndRepo(c *context.APIContext) (*db.User, *db.Repository) {
|
||||
owner, err := db.GetUserByName(c.Params(":username"))
|
||||
if err != nil {
|
||||
if errors.IsUserNotExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("GetUserByName", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
repo, err := db.GetRepositoryByName(owner.ID, c.Params(":reponame"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetRepositoryByName", errors.IsRepoNotExist, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return owner, repo
|
||||
}
|
||||
|
||||
func Get(c *context.APIContext) {
|
||||
_, repo := parseOwnerAndRepo(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSONSuccess(repo.APIFormat(&api.Permission{
|
||||
Admin: c.Repo.IsAdmin(),
|
||||
Push: c.Repo.IsWriter(),
|
||||
Pull: true,
|
||||
}))
|
||||
}
|
||||
|
||||
func Delete(c *context.APIContext) {
|
||||
owner, repo := parseOwnerAndRepo(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if owner.IsOrganization() && !owner.IsOwnedBy(c.User.ID) {
|
||||
c.Error(http.StatusForbidden, "", "given user is not owner of organization")
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DeleteRepository(owner.ID, repo.ID); err != nil {
|
||||
c.ServerError("DeleteRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name)
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func ListForks(c *context.APIContext) {
|
||||
forks, err := c.Repo.Repository.GetForks()
|
||||
if err != nil {
|
||||
c.ServerError("GetForks", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiForks := make([]*api.Repository, len(forks))
|
||||
for i := range forks {
|
||||
if err := forks[i].GetOwner(); err != nil {
|
||||
c.ServerError("GetOwner", err)
|
||||
return
|
||||
}
|
||||
apiForks[i] = forks[i].APIFormat(&api.Permission{
|
||||
Admin: c.User.IsAdminOfRepo(forks[i]),
|
||||
Push: c.User.IsWriterOfRepo(forks[i]),
|
||||
Pull: true,
|
||||
})
|
||||
}
|
||||
|
||||
c.JSONSuccess(&apiForks)
|
||||
}
|
||||
|
||||
func IssueTracker(c *context.APIContext, form api.EditIssueTrackerOption) {
|
||||
_, repo := parseOwnerAndRepo(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if form.EnableIssues != nil {
|
||||
repo.EnableIssues = *form.EnableIssues
|
||||
}
|
||||
if form.EnableExternalTracker != nil {
|
||||
repo.EnableExternalTracker = *form.EnableExternalTracker
|
||||
}
|
||||
if form.ExternalTrackerURL != nil {
|
||||
repo.ExternalTrackerURL = *form.ExternalTrackerURL
|
||||
}
|
||||
if form.TrackerURLFormat != nil {
|
||||
repo.ExternalTrackerFormat = *form.TrackerURLFormat
|
||||
}
|
||||
if form.TrackerIssueStyle != nil {
|
||||
repo.ExternalTrackerStyle = *form.TrackerIssueStyle
|
||||
}
|
||||
|
||||
if err := db.UpdateRepository(repo, false); err != nil {
|
||||
c.ServerError("UpdateRepository", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func MirrorSync(c *context.APIContext) {
|
||||
_, repo := parseOwnerAndRepo(c)
|
||||
if c.Written() {
|
||||
return
|
||||
} else if !repo.IsMirror {
|
||||
c.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
go db.MirrorQueue.Add(repo.ID)
|
||||
c.Status(http.StatusAccepted)
|
||||
}
|
||||
45
internal/route/api/v1/user/app.go
Normal file
45
internal/route/api/v1/user/app.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
)
|
||||
|
||||
func ListAccessTokens(c *context.APIContext) {
|
||||
tokens, err := db.ListAccessTokens(c.User.ID)
|
||||
if err != nil {
|
||||
c.ServerError("ListAccessTokens", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiTokens := make([]*api.AccessToken, len(tokens))
|
||||
for i := range tokens {
|
||||
apiTokens[i] = &api.AccessToken{tokens[i].Name, tokens[i].Sha1}
|
||||
}
|
||||
c.JSONSuccess(&apiTokens)
|
||||
}
|
||||
|
||||
func CreateAccessToken(c *context.APIContext, form api.CreateAccessTokenOption) {
|
||||
t := &db.AccessToken{
|
||||
UID: c.User.ID,
|
||||
Name: form.Name,
|
||||
}
|
||||
if err := db.NewAccessToken(t); err != nil {
|
||||
if errors.IsAccessTokenNameAlreadyExist(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||
} else {
|
||||
c.ServerError("NewAccessToken", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, &api.AccessToken{t.Name, t.Sha1})
|
||||
}
|
||||
81
internal/route/api/v1/user/email.go
Normal file
81
internal/route/api/v1/user/email.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
"net/http"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func ListEmails(c *context.APIContext) {
|
||||
emails, err := db.GetEmailAddresses(c.User.ID)
|
||||
if err != nil {
|
||||
c.ServerError("GetEmailAddresses", err)
|
||||
return
|
||||
}
|
||||
apiEmails := make([]*api.Email, len(emails))
|
||||
for i := range emails {
|
||||
apiEmails[i] = convert2.ToEmail(emails[i])
|
||||
}
|
||||
c.JSONSuccess(&apiEmails)
|
||||
}
|
||||
|
||||
func AddEmail(c *context.APIContext, form api.CreateEmailOption) {
|
||||
if len(form.Emails) == 0 {
|
||||
c.Status(http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
|
||||
emails := make([]*db.EmailAddress, len(form.Emails))
|
||||
for i := range form.Emails {
|
||||
emails[i] = &db.EmailAddress{
|
||||
UID: c.User.ID,
|
||||
Email: form.Emails[i],
|
||||
IsActivated: !setting.Service.RegisterEmailConfirm,
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.AddEmailAddresses(emails); err != nil {
|
||||
if db.IsErrEmailAlreadyUsed(err) {
|
||||
c.Error(http.StatusUnprocessableEntity, "", "email address has been used: "+err.(db.ErrEmailAlreadyUsed).Email)
|
||||
} else {
|
||||
c.Error(http.StatusInternalServerError, "AddEmailAddresses", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
apiEmails := make([]*api.Email, len(emails))
|
||||
for i := range emails {
|
||||
apiEmails[i] = convert2.ToEmail(emails[i])
|
||||
}
|
||||
c.JSON(http.StatusCreated, &apiEmails)
|
||||
}
|
||||
|
||||
func DeleteEmail(c *context.APIContext, form api.CreateEmailOption) {
|
||||
if len(form.Emails) == 0 {
|
||||
c.NoContent()
|
||||
return
|
||||
}
|
||||
|
||||
emails := make([]*db.EmailAddress, len(form.Emails))
|
||||
for i := range form.Emails {
|
||||
emails[i] = &db.EmailAddress{
|
||||
UID: c.User.ID,
|
||||
Email: form.Emails[i],
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.DeleteEmailAddresses(emails); err != nil {
|
||||
c.Error(http.StatusInternalServerError, "DeleteEmailAddresses", err)
|
||||
return
|
||||
}
|
||||
c.NoContent()
|
||||
}
|
||||
114
internal/route/api/v1/user/follower.go
Normal file
114
internal/route/api/v1/user/follower.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
func responseApiUsers(c *context.APIContext, users []*db.User) {
|
||||
apiUsers := make([]*api.User, len(users))
|
||||
for i := range users {
|
||||
apiUsers[i] = users[i].APIFormat()
|
||||
}
|
||||
c.JSONSuccess(&apiUsers)
|
||||
}
|
||||
|
||||
func listUserFollowers(c *context.APIContext, u *db.User) {
|
||||
users, err := u.GetFollowers(c.QueryInt("page"))
|
||||
if err != nil {
|
||||
c.ServerError("GetUserFollowers", err)
|
||||
return
|
||||
}
|
||||
responseApiUsers(c, users)
|
||||
}
|
||||
|
||||
func ListMyFollowers(c *context.APIContext) {
|
||||
listUserFollowers(c, c.User)
|
||||
}
|
||||
|
||||
func ListFollowers(c *context.APIContext) {
|
||||
u := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
listUserFollowers(c, u)
|
||||
}
|
||||
|
||||
func listUserFollowing(c *context.APIContext, u *db.User) {
|
||||
users, err := u.GetFollowing(c.QueryInt("page"))
|
||||
if err != nil {
|
||||
c.ServerError("GetFollowing", err)
|
||||
return
|
||||
}
|
||||
responseApiUsers(c, users)
|
||||
}
|
||||
|
||||
func ListMyFollowing(c *context.APIContext) {
|
||||
listUserFollowing(c, c.User)
|
||||
}
|
||||
|
||||
func ListFollowing(c *context.APIContext) {
|
||||
u := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
listUserFollowing(c, u)
|
||||
}
|
||||
|
||||
func checkUserFollowing(c *context.APIContext, u *db.User, followID int64) {
|
||||
if u.IsFollowing(followID) {
|
||||
c.NoContent()
|
||||
} else {
|
||||
c.NotFound()
|
||||
}
|
||||
}
|
||||
|
||||
func CheckMyFollowing(c *context.APIContext) {
|
||||
target := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
checkUserFollowing(c, c.User, target.ID)
|
||||
}
|
||||
|
||||
func CheckFollowing(c *context.APIContext) {
|
||||
u := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
target := GetUserByParamsName(c, ":target")
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
checkUserFollowing(c, u, target.ID)
|
||||
}
|
||||
|
||||
func Follow(c *context.APIContext) {
|
||||
target := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
if err := db.FollowUser(c.User.ID, target.ID); err != nil {
|
||||
c.ServerError("FollowUser", err)
|
||||
return
|
||||
}
|
||||
c.NoContent()
|
||||
}
|
||||
|
||||
func Unfollow(c *context.APIContext) {
|
||||
target := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
if err := db.UnfollowUser(c.User.ID, target.ID); err != nil {
|
||||
c.ServerError("UnfollowUser", err)
|
||||
return
|
||||
}
|
||||
c.NoContent()
|
||||
}
|
||||
108
internal/route/api/v1/user/key.go
Normal file
108
internal/route/api/v1/user/key.go
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
convert2 "gogs.io/gogs/internal/route/api/v1/convert"
|
||||
repo2 "gogs.io/gogs/internal/route/api/v1/repo"
|
||||
"net/http"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/setting"
|
||||
)
|
||||
|
||||
func GetUserByParamsName(c *context.APIContext, name string) *db.User {
|
||||
user, err := db.GetUserByName(c.Params(name))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
|
||||
return nil
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
// GetUserByParams returns user whose name is presented in URL paramenter.
|
||||
func GetUserByParams(c *context.APIContext) *db.User {
|
||||
return GetUserByParamsName(c, ":username")
|
||||
}
|
||||
|
||||
func composePublicKeysAPILink() string {
|
||||
return setting.AppURL + "api/v1/user/keys/"
|
||||
}
|
||||
|
||||
func listPublicKeys(c *context.APIContext, uid int64) {
|
||||
keys, err := db.ListPublicKeys(uid)
|
||||
if err != nil {
|
||||
c.ServerError("ListPublicKeys", err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLink := composePublicKeysAPILink()
|
||||
apiKeys := make([]*api.PublicKey, len(keys))
|
||||
for i := range keys {
|
||||
apiKeys[i] = convert2.ToPublicKey(apiLink, keys[i])
|
||||
}
|
||||
|
||||
c.JSONSuccess(&apiKeys)
|
||||
}
|
||||
|
||||
func ListMyPublicKeys(c *context.APIContext) {
|
||||
listPublicKeys(c, c.User.ID)
|
||||
}
|
||||
|
||||
func ListPublicKeys(c *context.APIContext) {
|
||||
user := GetUserByParams(c)
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
listPublicKeys(c, user.ID)
|
||||
}
|
||||
|
||||
func GetPublicKey(c *context.APIContext) {
|
||||
key, err := db.GetPublicKeyByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetPublicKeyByID", db.IsErrKeyNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
apiLink := composePublicKeysAPILink()
|
||||
c.JSONSuccess(convert2.ToPublicKey(apiLink, key))
|
||||
}
|
||||
|
||||
// CreateUserPublicKey creates new public key to given user by ID.
|
||||
func CreateUserPublicKey(c *context.APIContext, form api.CreateKeyOption, uid int64) {
|
||||
content, err := db.CheckPublicKeyString(form.Key)
|
||||
if err != nil {
|
||||
repo2.HandleCheckKeyStringError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
key, err := db.AddPublicKey(uid, form.Title, content)
|
||||
if err != nil {
|
||||
repo2.HandleAddKeyError(c, err)
|
||||
return
|
||||
}
|
||||
apiLink := composePublicKeysAPILink()
|
||||
c.JSON(http.StatusCreated, convert2.ToPublicKey(apiLink, key))
|
||||
}
|
||||
|
||||
func CreatePublicKey(c *context.APIContext, form api.CreateKeyOption) {
|
||||
CreateUserPublicKey(c, form, c.User.ID)
|
||||
}
|
||||
|
||||
func DeletePublicKey(c *context.APIContext) {
|
||||
if err := db.DeletePublicKey(c.User, c.ParamsInt64(":id")); err != nil {
|
||||
if db.IsErrKeyAccessDenied(err) {
|
||||
c.Error(http.StatusForbidden, "", "you do not have access to this key")
|
||||
} else {
|
||||
c.Error(http.StatusInternalServerError, "DeletePublicKey", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.NoContent()
|
||||
}
|
||||
74
internal/route/api/v1/user/user.go
Normal file
74
internal/route/api/v1/user/user.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
|
||||
api "github.com/gogs/go-gogs-client"
|
||||
|
||||
"gogs.io/gogs/internal/context"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/db/errors"
|
||||
"gogs.io/gogs/internal/markup"
|
||||
)
|
||||
|
||||
func Search(c *context.APIContext) {
|
||||
opts := &db.SearchUserOptions{
|
||||
Keyword: c.Query("q"),
|
||||
Type: db.USER_TYPE_INDIVIDUAL,
|
||||
PageSize: com.StrTo(c.Query("limit")).MustInt(),
|
||||
}
|
||||
if opts.PageSize == 0 {
|
||||
opts.PageSize = 10
|
||||
}
|
||||
|
||||
users, _, err := db.SearchUserByName(opts)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||
"ok": false,
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
results := make([]*api.User, len(users))
|
||||
for i := range users {
|
||||
results[i] = &api.User{
|
||||
ID: users[i].ID,
|
||||
UserName: users[i].Name,
|
||||
AvatarUrl: users[i].AvatarLink(),
|
||||
FullName: markup.Sanitize(users[i].FullName),
|
||||
}
|
||||
if c.IsLogged {
|
||||
results[i].Email = users[i].Email
|
||||
}
|
||||
}
|
||||
|
||||
c.JSONSuccess(map[string]interface{}{
|
||||
"ok": true,
|
||||
"data": results,
|
||||
})
|
||||
}
|
||||
|
||||
func GetInfo(c *context.APIContext) {
|
||||
u, err := db.GetUserByName(c.Params(":username"))
|
||||
if err != nil {
|
||||
c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Hide user e-mail when API caller isn't signed in.
|
||||
if !c.IsLogged {
|
||||
u.Email = ""
|
||||
}
|
||||
c.JSONSuccess(u.APIFormat())
|
||||
}
|
||||
|
||||
func GetAuthenticatedUser(c *context.APIContext) {
|
||||
c.JSONSuccess(c.User.APIFormat())
|
||||
}
|
||||
Reference in New Issue
Block a user