diff --git a/README.md b/README.md
index faef7915f..e68f78a45 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
![](public/img/gogs-large-resize.png)
-##### Current version: 0.7.28 Beta
+##### Current version: 0.7.29 Beta
diff --git a/cmd/web.go b/cmd/web.go
index 808b03ecd..5f1e44f3a 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -29,11 +29,8 @@ import (
"gopkg.in/ini.v1"
"gopkg.in/macaron.v1"
- api "github.com/gogits/go-gogs-client"
-
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
- "github.com/gogits/gogs/modules/auth/apiv1"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/log"
@@ -42,7 +39,7 @@ import (
"github.com/gogits/gogs/modules/template"
"github.com/gogits/gogs/routers"
"github.com/gogits/gogs/routers/admin"
- "github.com/gogits/gogs/routers/api/v1"
+ apiv1 "github.com/gogits/gogs/routers/api/v1"
"github.com/gogits/gogs/routers/dev"
"github.com/gogits/gogs/routers/org"
"github.com/gogits/gogs/routers/repo"
@@ -186,7 +183,6 @@ func runWeb(ctx *cli.Context) {
ignSignInAndCsrf := middleware.Toggle(&middleware.ToggleOptions{DisableCsrf: true})
reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true})
- bind := binding.Bind
bindIgnErr := binding.BindIgnErr
// Routers.
@@ -197,76 +193,8 @@ func runWeb(ctx *cli.Context) {
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
// ***** START: API *****
- // FIXME: custom form error response
m.Group("/api", func() {
- m.Group("/v1", func() {
- // Miscellaneous
- m.Post("/markdown", bindIgnErr(apiv1.MarkdownForm{}), v1.Markdown)
- m.Post("/markdown/raw", v1.MarkdownRaw)
-
- // Users
- m.Group("/users", func() {
- m.Get("/search", v1.SearchUsers)
-
- m.Group("/:username", func() {
- m.Get("", v1.GetUserInfo)
-
- m.Group("/tokens", func() {
- m.Combo("").Get(v1.ListAccessTokens).
- Post(bind(v1.CreateAccessTokenForm{}), v1.CreateAccessToken)
- }, middleware.ApiReqBasicAuth())
- })
- })
-
- m.Group("/users", func() {
- m.Group("/:username", func() {
- m.Get("/keys", v1.ListUserPublicKeys)
- })
- }, middleware.ApiReqToken())
-
- m.Group("/user", func() {
- m.Group("/keys", func() {
- m.Combo("").Get(v1.ListMyPublicKeys).
- Post(bind(api.CreateKeyOption{}), v1.CreateUserPublicKey)
- m.Combo("/:id").Get(v1.GetUserPublicKey).
- Delete(v1.DeleteUserPublicKey)
- })
- }, middleware.ApiReqToken())
-
- // Repositories
- m.Combo("/user/repos", middleware.ApiReqToken()).Get(v1.ListMyRepos).
- Post(bind(api.CreateRepoOption{}), v1.CreateRepo)
- m.Post("/org/:org/repos", middleware.ApiReqToken(), bind(api.CreateRepoOption{}), v1.CreateOrgRepo)
-
- m.Group("/repos", func() {
- m.Get("/search", v1.SearchRepos)
- })
-
- m.Group("/repos", func() {
- m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), v1.MigrateRepo)
- m.Combo("/:username/:reponame").Get(v1.GetRepo).
- Delete(v1.DeleteRepo)
-
- m.Group("/:username/:reponame", func() {
- m.Combo("/hooks").Get(v1.ListRepoHooks).
- Post(bind(api.CreateHookOption{}), v1.CreateRepoHook)
- m.Patch("/hooks/:id:int", bind(api.EditHookOption{}), v1.EditRepoHook)
- m.Get("/raw/*", middleware.RepoRef(), v1.GetRepoRawFile)
- m.Get("/archive/*", v1.GetRepoArchive)
-
- m.Group("/keys", func() {
- m.Combo("").Get(v1.ListRepoDeployKeys).
- Post(bind(api.CreateKeyOption{}), v1.CreateRepoDeployKey)
- m.Combo("/:id").Get(v1.GetRepoDeployKey).
- Delete(v1.DeleteRepoDeploykey)
- })
- }, middleware.ApiRepoAssignment())
- }, middleware.ApiReqToken())
-
- m.Any("/*", func(ctx *middleware.Context) {
- ctx.Error(404)
- })
- })
+ apiv1.RegisterRoutes(m)
}, ignSignIn)
// ***** END: API *****
diff --git a/gogs.go b/gogs.go
index cb4ea9e2e..cd13dd218 100644
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.7.28.1203 Beta"
+const APP_VER = "0.7.29.1204 Beta"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/modules/auth/apiv1/miscellaneous.go b/modules/auth/apiv1/miscellaneous.go
deleted file mode 100644
index 5032f0ac7..000000000
--- a/modules/auth/apiv1/miscellaneous.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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 apiv1
-
-import (
- "reflect"
-
- "github.com/go-macaron/binding"
- "gopkg.in/macaron.v1"
-
- "github.com/gogits/gogs/modules/auth"
-)
-
-type MarkdownForm struct {
- Text string
- Mode string
- Context string
-}
-
-func (f *MarkdownForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
- return validateApiReq(errs, ctx.Data, f)
-}
-
-func validateApiReq(errs binding.Errors, data map[string]interface{}, f auth.Form) binding.Errors {
- if errs.Len() == 0 {
- return errs
- }
-
- data["HasError"] = true
-
- typ := reflect.TypeOf(f)
- val := reflect.ValueOf(f)
-
- if typ.Kind() == reflect.Ptr {
- typ = typ.Elem()
- val = val.Elem()
- }
-
- for i := 0; i < typ.NumField(); i++ {
- field := typ.Field(i)
-
- fieldName := field.Tag.Get("form")
- // Allow ignored fields in the struct
- if fieldName == "-" {
- continue
- }
-
- if errs[0].FieldNames[0] == field.Name {
- switch errs[0].Classification {
- case binding.ERR_REQUIRED:
- data["ErrorMsg"] = fieldName + " cannot be empty"
- case binding.ERR_ALPHA_DASH:
- data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) characters"
- case binding.ERR_ALPHA_DASH_DOT:
- data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) or dot characters"
- case binding.ERR_MIN_SIZE:
- data["ErrorMsg"] = fieldName + " must contain at least " + auth.GetMinSize(field) + " characters"
- case binding.ERR_MAX_SIZE:
- data["ErrorMsg"] = fieldName + " must contain at most " + auth.GetMaxSize(field) + " characters"
- case binding.ERR_EMAIL:
- data["ErrorMsg"] = fieldName + " is not a valid e-mail address"
- case binding.ERR_URL:
- data["ErrorMsg"] = fieldName + " is not a valid URL"
- default:
- data["ErrorMsg"] = "Unknown error: " + errs[0].Classification
- }
- return errs
- }
- }
- return errs
-}
diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go
index 078bdfdc5..1f979c343 100644
--- a/modules/middleware/auth.go
+++ b/modules/middleware/auth.go
@@ -130,22 +130,3 @@ func Toggle(options *ToggleOptions) macaron.Handler {
}
}
}
-
-// Contexter middleware already checks token for user sign in process.
-func ApiReqToken() macaron.Handler {
- return func(ctx *Context) {
- if !ctx.IsSigned {
- ctx.Error(401)
- return
- }
- }
-}
-
-func ApiReqBasicAuth() macaron.Handler {
- return func(ctx *Context) {
- if !ctx.IsBasicAuth {
- ctx.Error(401)
- return
- }
- }
-}
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index 46df9f04e..78bab4c56 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -17,66 +17,6 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-func ApiRepoAssignment() macaron.Handler {
- return func(ctx *Context) {
- ctx.Repo = &RepoContext{}
-
- userName := ctx.Params(":username")
- repoName := ctx.Params(":reponame")
-
- var (
- owner *models.User
- err error
- )
-
- // Check if the user is the same as the repository owner.
- if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
- owner = ctx.User
- } else {
- owner, err = models.GetUserByName(userName)
- if err != nil {
- if models.IsErrUserNotExist(err) {
- ctx.Error(404)
- } else {
- ctx.APIError(500, "GetUserByName", err)
- }
- return
- }
- }
- ctx.Repo.Owner = owner
-
- // Get repository.
- repo, err := models.GetRepositoryByName(owner.Id, repoName)
- if err != nil {
- if models.IsErrRepoNotExist(err) {
- ctx.Error(404)
- } else {
- ctx.APIError(500, "GetRepositoryByName", err)
- }
- return
- } else if err = repo.GetOwner(); err != nil {
- ctx.APIError(500, "GetOwner", err)
- return
- }
-
- mode, err := models.AccessLevel(ctx.User, repo)
- if err != nil {
- ctx.APIError(500, "AccessLevel", err)
- return
- }
-
- ctx.Repo.AccessMode = mode
-
- // Check access.
- if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
- ctx.Error(404)
- return
- }
-
- ctx.Repo.Repository = repo
- }
-}
-
// RepoRef handles repository reference name including those contain `/`.
func RepoRef() macaron.Handler {
return func(ctx *Context) {
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
new file mode 100644
index 000000000..d2ebd1b11
--- /dev/null
+++ b/routers/api/v1/api.go
@@ -0,0 +1,185 @@
+// 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 (
+ "strings"
+
+ "github.com/go-macaron/binding"
+ "gopkg.in/macaron.v1"
+
+ api "github.com/gogits/go-gogs-client"
+
+ "github.com/gogits/gogs/models"
+ "github.com/gogits/gogs/modules/auth"
+ "github.com/gogits/gogs/modules/middleware"
+ "github.com/gogits/gogs/routers/api/v1/misc"
+ "github.com/gogits/gogs/routers/api/v1/repo"
+ "github.com/gogits/gogs/routers/api/v1/user"
+)
+
+func RepoAssignment() macaron.Handler {
+ return func(ctx *middleware.Context) {
+ ctx.Repo = &middleware.RepoContext{}
+
+ userName := ctx.Params(":username")
+ repoName := ctx.Params(":reponame")
+
+ var (
+ owner *models.User
+ err error
+ )
+
+ // Check if the user is the same as the repository owner.
+ if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
+ owner = ctx.User
+ } else {
+ owner, err = models.GetUserByName(userName)
+ if err != nil {
+ if models.IsErrUserNotExist(err) {
+ ctx.Error(404)
+ } else {
+ ctx.APIError(500, "GetUserByName", err)
+ }
+ return
+ }
+ }
+ ctx.Repo.Owner = owner
+
+ // Get repository.
+ repo, err := models.GetRepositoryByName(owner.Id, repoName)
+ if err != nil {
+ if models.IsErrRepoNotExist(err) {
+ ctx.Error(404)
+ } else {
+ ctx.APIError(500, "GetRepositoryByName", err)
+ }
+ return
+ } else if err = repo.GetOwner(); err != nil {
+ ctx.APIError(500, "GetOwner", err)
+ return
+ }
+
+ mode, err := models.AccessLevel(ctx.User, repo)
+ if err != nil {
+ ctx.APIError(500, "AccessLevel", err)
+ return
+ }
+
+ ctx.Repo.AccessMode = mode
+
+ // Check access.
+ if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
+ ctx.Error(404)
+ return
+ }
+
+ ctx.Repo.Repository = repo
+ }
+}
+
+// Contexter middleware already checks token for user sign in process.
+func ReqToken() macaron.Handler {
+ return func(ctx *middleware.Context) {
+ if !ctx.IsSigned {
+ ctx.Error(401)
+ return
+ }
+ }
+}
+
+func ReqBasicAuth() macaron.Handler {
+ return func(ctx *middleware.Context) {
+ if !ctx.IsBasicAuth {
+ ctx.Error(401)
+ return
+ }
+ }
+}
+
+func ReqAdmin() macaron.Handler {
+ return func(ctx *middleware.Context) {
+ if !ctx.User.IsAdmin {
+ ctx.Error(403)
+ return
+ }
+ }
+}
+
+// RegisterRoutes registers all v1 APIs routes to web application.
+// FIXME: custom form error response
+func RegisterRoutes(m *macaron.Macaron) {
+ bind := binding.Bind
+
+ m.Group("/v1", func() {
+ // Miscellaneous
+ m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
+ m.Post("/markdown/raw", misc.MarkdownRaw)
+
+ // Users
+ m.Group("/users", func() {
+ m.Get("/search", user.Search)
+
+ m.Group("/:username", func() {
+ m.Get("", user.GetInfo)
+
+ m.Group("/tokens", func() {
+ m.Combo("").Get(user.ListAccessTokens).
+ Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
+ }, ReqBasicAuth())
+ })
+ })
+
+ m.Group("/users", func() {
+ m.Group("/:username", func() {
+ m.Combo("/keys").Get(user.ListPublicKeys).
+ Post(ReqAdmin(), user.CreateUserPublicKey)
+ })
+ }, ReqToken())
+
+ m.Group("/user", func() {
+ m.Group("/keys", func() {
+ m.Combo("").Get(user.ListMyPublicKeys).
+ Post(bind(api.CreateKeyOption{}), user.CreatePublicKey)
+ m.Combo("/:id").Get(user.GetPublicKey).
+ Delete(user.DeletePublicKey)
+ })
+ }, ReqToken())
+
+ // Repositories
+ m.Combo("/user/repos", ReqToken()).Get(repo.ListMyRepos).
+ Post(bind(api.CreateRepoOption{}), repo.Create)
+ m.Post("/org/:org/repos", ReqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
+
+ m.Group("/repos", func() {
+ m.Get("/search", repo.Search)
+ })
+
+ m.Group("/repos", func() {
+ m.Post("/migrate", bind(auth.MigrateRepoForm{}), repo.Migrate)
+ m.Combo("/:username/:reponame").Get(repo.Get).
+ Delete(repo.Delete)
+
+ m.Group("/:username/:reponame", func() {
+ m.Combo("/hooks").Get(repo.ListHooks).
+ Post(bind(api.CreateHookOption{}), repo.CreateHook)
+ m.Patch("/hooks/:id:int", bind(api.EditHookOption{}), repo.EditHook)
+ m.Get("/raw/*", middleware.RepoRef(), repo.GetRawFile)
+ m.Get("/archive/*", repo.GetArchive)
+
+ m.Group("/keys", func() {
+ m.Combo("").Get(repo.ListDeployKeys).
+ Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
+ m.Combo("/:id").Get(repo.GetDeployKey).
+ Delete(repo.DeleteDeploykey)
+ })
+ }, RepoAssignment())
+ }, ReqToken())
+
+ m.Any("/*", func(ctx *middleware.Context) {
+ ctx.Error(404)
+ })
+ })
+}
diff --git a/routers/api/v1/miscellaneous.go b/routers/api/v1/misc/markdown.go
similarity index 88%
rename from routers/api/v1/miscellaneous.go
rename to routers/api/v1/misc/markdown.go
index a382e3495..49979ef76 100644
--- a/routers/api/v1/miscellaneous.go
+++ b/routers/api/v1/misc/markdown.go
@@ -2,16 +2,17 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package misc
import (
- "github.com/gogits/gogs/modules/auth/apiv1"
+ api "github.com/gogits/go-gogs-client"
+
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/middleware"
)
// https://github.com/gogits/go-gogs-client/wiki/Miscellaneous#render-an-arbitrary-markdown-document
-func Markdown(ctx *middleware.Context, form apiv1.MarkdownForm) {
+func Markdown(ctx *middleware.Context, form api.MarkdownOption) {
if ctx.HasApiError() {
ctx.APIError(422, "", ctx.GetErrMsg())
return
diff --git a/routers/api/v1/repo_file.go b/routers/api/v1/repo/file.go
similarity index 91%
rename from routers/api/v1/repo_file.go
rename to routers/api/v1/repo/file.go
index 8cf36aefd..0279718bb 100644
--- a/routers/api/v1/repo_file.go
+++ b/routers/api/v1/repo/file.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package repo
import (
"github.com/gogits/gogs/models"
@@ -12,7 +12,7 @@ import (
)
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Contents#download-raw-content
-func GetRepoRawFile(ctx *middleware.Context) {
+func GetRawFile(ctx *middleware.Context) {
if !ctx.Repo.HasAccess() {
ctx.Error(404)
return
@@ -33,7 +33,7 @@ func GetRepoRawFile(ctx *middleware.Context) {
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Contents#download-archive
-func GetRepoArchive(ctx *middleware.Context) {
+func GetArchive(ctx *middleware.Context) {
repoPath := models.RepoPath(ctx.Params(":username"), ctx.Params(":reponame"))
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
diff --git a/routers/api/v1/repo_hooks.go b/routers/api/v1/repo/hooks.go
similarity index 79%
rename from routers/api/v1/repo_hooks.go
rename to routers/api/v1/repo/hooks.go
index 77c2ba660..1ec708867 100644
--- a/routers/api/v1/repo_hooks.go
+++ b/routers/api/v1/repo/hooks.go
@@ -2,11 +2,10 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package repo
import (
"encoding/json"
- "fmt"
"github.com/Unknwon/com"
@@ -14,36 +13,11 @@ import (
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
+ to "github.com/gogits/gogs/routers/api/v1/utils"
)
-// ToApiHook converts webhook to API format.
-func ToApiHook(repoLink string, w *models.Webhook) *api.Hook {
- config := map[string]string{
- "url": w.URL,
- "content_type": w.ContentType.Name(),
- }
- if w.HookTaskType == models.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,
- }
-}
-
// https://github.com/gogits/go-gogs-client/wiki/Repositories#list-hooks
-func ListRepoHooks(ctx *middleware.Context) {
+func ListHooks(ctx *middleware.Context) {
hooks, err := models.GetWebhooksByRepoID(ctx.Repo.Repository.ID)
if err != nil {
ctx.APIError(500, "GetWebhooksByRepoID", err)
@@ -52,14 +26,14 @@ func ListRepoHooks(ctx *middleware.Context) {
apiHooks := make([]*api.Hook, len(hooks))
for i := range hooks {
- apiHooks[i] = ToApiHook(ctx.Repo.RepoLink, hooks[i])
+ apiHooks[i] = to.ApiHook(ctx.Repo.RepoLink, hooks[i])
}
ctx.JSON(200, &apiHooks)
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#create-a-hook
-func CreateRepoHook(ctx *middleware.Context, form api.CreateHookOption) {
+func CreateHook(ctx *middleware.Context, form api.CreateHookOption) {
if !models.IsValidHookTaskType(form.Type) {
ctx.APIError(422, "", "Invalid hook type")
return
@@ -120,11 +94,11 @@ func CreateRepoHook(ctx *middleware.Context, form api.CreateHookOption) {
return
}
- ctx.JSON(201, ToApiHook(ctx.Repo.RepoLink, w))
+ ctx.JSON(201, to.ApiHook(ctx.Repo.RepoLink, w))
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#edit-a-hook
-func EditRepoHook(ctx *middleware.Context, form api.EditHookOption) {
+func EditHook(ctx *middleware.Context, form api.EditHookOption) {
w, err := models.GetWebhookByID(ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrWebhookNotExist(err) {
@@ -187,5 +161,5 @@ func EditRepoHook(ctx *middleware.Context, form api.EditHookOption) {
return
}
- ctx.JSON(200, ToApiHook(ctx.Repo.RepoLink, w))
+ ctx.JSON(200, to.ApiHook(ctx.Repo.RepoLink, w))
}
diff --git a/routers/api/v1/repo_keys.go b/routers/api/v1/repo/keys.go
similarity index 75%
rename from routers/api/v1/repo_keys.go
rename to routers/api/v1/repo/keys.go
index d8371b5a9..b0d8f9146 100644
--- a/routers/api/v1/repo_keys.go
+++ b/routers/api/v1/repo/keys.go
@@ -2,37 +2,25 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package repo
import (
"fmt"
- "github.com/Unknwon/com"
-
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting"
+ to "github.com/gogits/gogs/routers/api/v1/utils"
)
-func ToApiDeployKey(apiLink string, key *models.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 composeDeployKeysAPILink(repoPath string) string {
return setting.AppUrl + "api/v1/repos/" + repoPath + "/keys/"
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Deploy-Keys#list-deploy-keys
-func ListRepoDeployKeys(ctx *middleware.Context) {
+func ListDeployKeys(ctx *middleware.Context) {
keys, err := models.ListDeployKeys(ctx.Repo.Repository.ID)
if err != nil {
ctx.Handle(500, "ListDeployKeys", err)
@@ -46,14 +34,14 @@ func ListRepoDeployKeys(ctx *middleware.Context) {
ctx.APIError(500, "GetContent", err)
return
}
- apiKeys[i] = ToApiDeployKey(apiLink, keys[i])
+ apiKeys[i] = to.ApiDeployKey(apiLink, keys[i])
}
ctx.JSON(200, &apiKeys)
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Deploy-Keys#get-a-deploy-key
-func GetRepoDeployKey(ctx *middleware.Context) {
+func GetDeployKey(ctx *middleware.Context) {
key, err := models.GetDeployKeyByID(ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrDeployKeyNotExist(err) {
@@ -70,10 +58,10 @@ func GetRepoDeployKey(ctx *middleware.Context) {
}
apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
- ctx.JSON(200, ToApiDeployKey(apiLink, key))
+ ctx.JSON(200, to.ApiDeployKey(apiLink, key))
}
-func handleCheckKeyStringError(ctx *middleware.Context, err error) {
+func HandleCheckKeyStringError(ctx *middleware.Context, err error) {
if models.IsErrKeyUnableVerify(err) {
ctx.APIError(422, "", "Unable to verify key content")
} else {
@@ -81,7 +69,7 @@ func handleCheckKeyStringError(ctx *middleware.Context, err error) {
}
}
-func handleAddKeyError(ctx *middleware.Context, err error) {
+func HandleAddKeyError(ctx *middleware.Context, err error) {
switch {
case models.IsErrKeyAlreadyExist(err):
ctx.APIError(422, "", "Key content has been used as non-deploy key")
@@ -93,26 +81,26 @@ func handleAddKeyError(ctx *middleware.Context, err error) {
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Deploy-Keys#add-a-new-deploy-key
-func CreateRepoDeployKey(ctx *middleware.Context, form api.CreateKeyOption) {
+func CreateDeployKey(ctx *middleware.Context, form api.CreateKeyOption) {
content, err := models.CheckPublicKeyString(form.Key)
if err != nil {
- handleCheckKeyStringError(ctx, err)
+ HandleCheckKeyStringError(ctx, err)
return
}
key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content)
if err != nil {
- handleAddKeyError(ctx, err)
+ HandleAddKeyError(ctx, err)
return
}
key.Content = content
apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name)
- ctx.JSON(201, ToApiDeployKey(apiLink, key))
+ ctx.JSON(201, to.ApiDeployKey(apiLink, key))
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories-Deploy-Keys#remove-a-deploy-key
-func DeleteRepoDeploykey(ctx *middleware.Context) {
+func DeleteDeploykey(ctx *middleware.Context) {
if err := models.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
if models.IsErrKeyAccessDenied(err) {
ctx.APIError(403, "", "You do not have access to this key")
diff --git a/routers/api/v1/repo.go b/routers/api/v1/repo/repo.go
similarity index 85%
rename from routers/api/v1/repo.go
rename to routers/api/v1/repo/repo.go
index 119a52b44..864cb4dd1 100644
--- a/routers/api/v1/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package repo
import (
"path"
@@ -16,26 +16,11 @@ import (
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting"
+ to "github.com/gogits/gogs/routers/api/v1/utils"
)
-// ToApiRepository converts repository to API format.
-func ToApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository {
- cl := repo.CloneLink()
- return &api.Repository{
- Id: repo.ID,
- Owner: *ToApiUser(owner),
- FullName: owner.Name + "/" + repo.Name,
- Private: repo.IsPrivate,
- Fork: repo.IsFork,
- HtmlUrl: setting.AppUrl + owner.Name + "/" + repo.Name,
- CloneUrl: cl.HTTPS,
- SshUrl: cl.SSH,
- Permissions: permission,
- }
-}
-
// https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories
-func SearchRepos(ctx *middleware.Context) {
+func Search(ctx *middleware.Context) {
opt := models.SearchOption{
Keyword: path.Base(ctx.Query("q")),
Uid: com.StrTo(ctx.Query("uid")).MustInt64(),
@@ -112,12 +97,12 @@ func ListMyRepos(ctx *middleware.Context) {
repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
for i := range ownRepos {
- repos[i] = ToApiRepository(ctx.User, ownRepos[i], api.Permission{true, true, true})
+ repos[i] = to.ApiRepository(ctx.User, ownRepos[i], api.Permission{true, true, true})
}
i := numOwnRepos
for repo, access := range accessibleRepos {
- repos[i] = ToApiRepository(repo.Owner, repo, api.Permission{
+ repos[i] = to.ApiRepository(repo.Owner, repo, api.Permission{
Admin: access >= models.ACCESS_MODE_ADMIN,
Push: access >= models.ACCESS_MODE_WRITE,
Pull: true,
@@ -154,11 +139,11 @@ func createRepo(ctx *middleware.Context, owner *models.User, opt api.CreateRepoO
return
}
- ctx.JSON(201, ToApiRepository(owner, repo, api.Permission{true, true, true}))
+ ctx.JSON(201, to.ApiRepository(owner, repo, api.Permission{true, true, true}))
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#create
-func CreateRepo(ctx *middleware.Context, opt api.CreateRepoOption) {
+func Create(ctx *middleware.Context, opt api.CreateRepoOption) {
// Shouldn't reach this condition, but just in case.
if ctx.User.IsOrganization() {
ctx.APIError(422, "", "not allowed creating repository for organization")
@@ -186,7 +171,7 @@ func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) {
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate
-func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
+func Migrate(ctx *middleware.Context, form auth.MigrateRepoForm) {
ctxUser := ctx.User
// Not equal means context user is an organization,
// or is another user/organization if current user is admin.
@@ -254,7 +239,7 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
}
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
- ctx.JSON(201, ToApiRepository(ctxUser, repo, api.Permission{true, true, true}))
+ ctx.JSON(201, to.ApiRepository(ctxUser, repo, api.Permission{true, true, true}))
}
func parseOwnerAndRepo(ctx *middleware.Context) (*models.User, *models.Repository) {
@@ -282,17 +267,17 @@ func parseOwnerAndRepo(ctx *middleware.Context) (*models.User, *models.Repositor
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#get
-func GetRepo(ctx *middleware.Context) {
+func Get(ctx *middleware.Context) {
owner, repo := parseOwnerAndRepo(ctx)
if ctx.Written() {
return
}
- ctx.JSON(200, ToApiRepository(owner, repo, api.Permission{true, true, true}))
+ ctx.JSON(200, to.ApiRepository(owner, repo, api.Permission{true, true, true}))
}
// https://github.com/gogits/go-gogs-client/wiki/Repositories#delete
-func DeleteRepo(ctx *middleware.Context) {
+func Delete(ctx *middleware.Context) {
owner, repo := parseOwnerAndRepo(ctx)
if ctx.Written() {
return
diff --git a/routers/api/v1/user_app.go b/routers/api/v1/user/app.go
similarity index 85%
rename from routers/api/v1/user_app.go
rename to routers/api/v1/user/app.go
index c1b83d60a..00aacbdc1 100644
--- a/routers/api/v1/user_app.go
+++ b/routers/api/v1/user/app.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package user
import (
api "github.com/gogits/go-gogs-client"
@@ -26,12 +26,8 @@ func ListAccessTokens(ctx *middleware.Context) {
ctx.JSON(200, &apiTokens)
}
-type CreateAccessTokenForm struct {
- Name string `json:"name" binding:"Required"`
-}
-
// https://github.com/gogits/go-gogs-client/wiki/Users#create-a-access-token
-func CreateAccessToken(ctx *middleware.Context, form CreateAccessTokenForm) {
+func CreateAccessToken(ctx *middleware.Context, form api.CreateAccessTokenOption) {
t := &models.AccessToken{
UID: ctx.User.Id,
Name: form.Name,
diff --git a/routers/api/v1/user_keys.go b/routers/api/v1/user/keys.go
similarity index 64%
rename from routers/api/v1/user_keys.go
rename to routers/api/v1/user/keys.go
index 54a51ef3f..597ee9f1e 100644
--- a/routers/api/v1/user_keys.go
+++ b/routers/api/v1/user/keys.go
@@ -2,33 +2,36 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package user
import (
- "github.com/Unknwon/com"
-
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting"
+ "github.com/gogits/gogs/routers/api/v1/repo"
+ to "github.com/gogits/gogs/routers/api/v1/utils"
)
-func ToApiPublicKey(apiLink string, key *models.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 getUserByParams(ctx *middleware.Context) *models.User {
+ user, err := models.GetUserByName(ctx.Params(":username"))
+ if err != nil {
+ if models.IsErrUserNotExist(err) {
+ ctx.Error(404)
+ } else {
+ ctx.APIError(500, "GetUserByName", err)
+ }
+ return nil
}
+ return user
}
func composePublicKeysAPILink() string {
return setting.AppUrl + "api/v1/user/keys/"
}
-func listUserPublicKeys(ctx *middleware.Context, uid int64) {
+func listPublicKeys(ctx *middleware.Context, uid int64) {
keys, err := models.ListPublicKeys(uid)
if err != nil {
ctx.APIError(500, "ListPublicKeys", err)
@@ -38,33 +41,28 @@ func listUserPublicKeys(ctx *middleware.Context, uid int64) {
apiLink := composePublicKeysAPILink()
apiKeys := make([]*api.PublicKey, len(keys))
for i := range keys {
- apiKeys[i] = ToApiPublicKey(apiLink, keys[i])
+ apiKeys[i] = to.ApiPublicKey(apiLink, keys[i])
}
ctx.JSON(200, &apiKeys)
}
+// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-your-public-keys
+func ListMyPublicKeys(ctx *middleware.Context) {
+ listPublicKeys(ctx, ctx.User.Id)
+}
+
// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-public-keys-for-a-user
-func ListUserPublicKeys(ctx *middleware.Context) {
- user, err := models.GetUserByName(ctx.Params(":username"))
- if err != nil {
- if models.IsErrUserNotExist(err) {
- ctx.Error(404)
- } else {
- ctx.APIError(500, "GetUserByName", err)
- }
+func ListPublicKeys(ctx *middleware.Context) {
+ user := getUserByParams(ctx)
+ if ctx.Written() {
return
}
- listUserPublicKeys(ctx, user.Id)
-}
-
-// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-your-public-keys
-func ListMyPublicKeys(ctx *middleware.Context) {
- listUserPublicKeys(ctx, ctx.User.Id)
+ listPublicKeys(ctx, user.Id)
}
// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#get-a-single-public-key
-func GetUserPublicKey(ctx *middleware.Context) {
+func GetPublicKey(ctx *middleware.Context) {
key, err := models.GetPublicKeyByID(ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrKeyNotExist(err) {
@@ -76,28 +74,41 @@ func GetUserPublicKey(ctx *middleware.Context) {
}
apiLink := composePublicKeysAPILink()
- ctx.JSON(200, ToApiPublicKey(apiLink, key))
+ ctx.JSON(200, to.ApiPublicKey(apiLink, key))
}
-// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key
-func CreateUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
+func createUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption, uid int64) {
content, err := models.CheckPublicKeyString(form.Key)
if err != nil {
- handleCheckKeyStringError(ctx, err)
+ repo.HandleCheckKeyStringError(ctx, err)
return
}
- key, err := models.AddPublicKey(ctx.User.Id, form.Title, content)
+ key, err := models.AddPublicKey(uid, form.Title, content)
if err != nil {
- handleAddKeyError(ctx, err)
+ repo.HandleAddKeyError(ctx, err)
return
}
apiLink := composePublicKeysAPILink()
- ctx.JSON(201, ToApiPublicKey(apiLink, key))
+ ctx.JSON(201, to.ApiPublicKey(apiLink, key))
+}
+
+// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key-for-user
+func CreateUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
+ user := getUserByParams(ctx)
+ if ctx.Written() {
+ return
+ }
+ createUserPublicKey(ctx, form, user.Id)
+}
+
+// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key
+func CreatePublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
+ createUserPublicKey(ctx, form, ctx.User.Id)
}
// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#delete-a-public-key
-func DeleteUserPublicKey(ctx *middleware.Context) {
+func DeletePublicKey(ctx *middleware.Context) {
if err := models.DeletePublicKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
if models.IsErrKeyAccessDenied(err) {
ctx.APIError(403, "", "You do not have access to this key")
diff --git a/routers/api/v1/user.go b/routers/api/v1/user/user.go
similarity index 82%
rename from routers/api/v1/user.go
rename to routers/api/v1/user/user.go
index 36a1872b9..6d4b52ffd 100644
--- a/routers/api/v1/user.go
+++ b/routers/api/v1/user/user.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package v1
+package user
import (
"github.com/Unknwon/com"
@@ -13,19 +13,8 @@ import (
"github.com/gogits/gogs/modules/middleware"
)
-// ToApiUser converts user to API format.
-func ToApiUser(u *models.User) *api.User {
- return &api.User{
- ID: u.Id,
- UserName: u.Name,
- FullName: u.FullName,
- Email: u.Email,
- AvatarUrl: u.AvatarLink(),
- }
-}
-
// https://github.com/gogits/go-gogs-client/wiki/Users#search-users
-func SearchUsers(ctx *middleware.Context) {
+func Search(ctx *middleware.Context) {
opt := models.SearchOption{
Keyword: ctx.Query("q"),
Limit: com.StrTo(ctx.Query("limit")).MustInt(),
@@ -63,7 +52,7 @@ func SearchUsers(ctx *middleware.Context) {
}
// https://github.com/gogits/go-gogs-client/wiki/Users#get-a-single-user
-func GetUserInfo(ctx *middleware.Context) {
+func GetInfo(ctx *middleware.Context) {
u, err := models.GetUserByName(ctx.Params(":username"))
if err != nil {
if models.IsErrUserNotExist(err) {
diff --git a/routers/api/v1/utils/convert.go b/routers/api/v1/utils/convert.go
new file mode 100644
index 000000000..7ac4edf26
--- /dev/null
+++ b/routers/api/v1/utils/convert.go
@@ -0,0 +1,92 @@
+// 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 utils
+
+import (
+ "fmt"
+
+ "github.com/Unknwon/com"
+
+ api "github.com/gogits/go-gogs-client"
+
+ "github.com/gogits/gogs/models"
+ "github.com/gogits/gogs/modules/setting"
+)
+
+// ApiUser converts user to its API format.
+func ApiUser(u *models.User) *api.User {
+ return &api.User{
+ ID: u.Id,
+ UserName: u.Name,
+ FullName: u.FullName,
+ Email: u.Email,
+ AvatarUrl: u.AvatarLink(),
+ }
+}
+
+// ApiRepository converts repository to API format.
+func ApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository {
+ cl := repo.CloneLink()
+ return &api.Repository{
+ Id: repo.ID,
+ Owner: *ApiUser(owner),
+ FullName: owner.Name + "/" + repo.Name,
+ Private: repo.IsPrivate,
+ Fork: repo.IsFork,
+ HtmlUrl: setting.AppUrl + owner.Name + "/" + repo.Name,
+ CloneUrl: cl.HTTPS,
+ SshUrl: cl.SSH,
+ Permissions: permission,
+ }
+}
+
+// ApiPublicKey converts public key to its API format.
+func ApiPublicKey(apiLink string, key *models.PublicKey) *api.PublicKey {
+ return &api.PublicKey{
+ ID: key.ID,
+ Key: key.Content,
+ URL: apiLink + com.ToStr(key.ID),
+ Title: key.Name,
+ Created: key.Created,
+ }
+}
+
+// ApiHook converts webhook to its API format.
+func ApiHook(repoLink string, w *models.Webhook) *api.Hook {
+ config := map[string]string{
+ "url": w.URL,
+ "content_type": w.ContentType.Name(),
+ }
+ if w.HookTaskType == models.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,
+ }
+}
+
+// ApiDeployKey converts deploy key to its API format.
+func ApiDeployKey(apiLink string, key *models.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.
+ }
+}
diff --git a/templates/.VERSION b/templates/.VERSION
index c817bbcab..ebd439271 100644
--- a/templates/.VERSION
+++ b/templates/.VERSION
@@ -1 +1 @@
-0.7.28.1203 Beta
\ No newline at end of file
+0.7.29.1204 Beta
\ No newline at end of file