moving API to api package, swagger annotatoins
This commit is contained in:
parent
e64ec7cf88
commit
0d04fa67e3
15 changed files with 249 additions and 159 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,6 +13,8 @@ drone_*
|
|||
.env
|
||||
temp/
|
||||
|
||||
api/swagger/files/*
|
||||
|
||||
# vendored repositories that we don't actually need
|
||||
# to vendor. so exclude them
|
||||
|
||||
|
|
1
api/build.go
Normal file
1
api/build.go
Normal file
|
@ -0,0 +1 @@
|
|||
package api
|
16
api/doc.go
Normal file
16
api/doc.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Package classification Drone API.
|
||||
//
|
||||
// Schemes: http, https
|
||||
// BasePath: /api
|
||||
// Version: 1.0.0
|
||||
//
|
||||
// Consumes:
|
||||
// - application/json
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// swagger:meta
|
||||
package api
|
||||
|
||||
//go:generate swagger generate spec -o swagger/files/swagger.json
|
|
@ -1,4 +1,4 @@
|
|||
package controller
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -8,8 +8,6 @@ import (
|
|||
|
||||
"github.com/drone/drone/model"
|
||||
"github.com/drone/drone/router/middleware/context"
|
||||
"github.com/drone/drone/router/middleware/session"
|
||||
"github.com/drone/drone/shared/token"
|
||||
"github.com/drone/drone/store"
|
||||
)
|
||||
|
||||
|
@ -22,13 +20,6 @@ func GetNodes(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func ShowNodes(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
nodes, _ := store.GetNodeList(c)
|
||||
token, _ := token.New(token.CsrfToken, user.Login).Sign(user.Hash)
|
||||
c.HTML(http.StatusOK, "nodes.html", gin.H{"User": user, "Nodes": nodes, "Csrf": token})
|
||||
}
|
||||
|
||||
func GetNode(c *gin.Context) {
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controller
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -150,11 +150,11 @@ func PatchRepo(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, repo)
|
||||
c.JSON(http.StatusOK, repo)
|
||||
}
|
||||
|
||||
func GetRepo(c *gin.Context) {
|
||||
c.IndentedJSON(http.StatusOK, session.Repo(c))
|
||||
c.JSON(http.StatusOK, session.Repo(c))
|
||||
}
|
||||
|
||||
func GetRepoKey(c *gin.Context) {
|
3
api/swagger/swagger.go
Normal file
3
api/swagger/swagger.go
Normal file
|
@ -0,0 +1,3 @@
|
|||
package swagger
|
||||
|
||||
//go:generate go-bindata -pkg swagger -o swagger_gen.go files/
|
113
api/user.go
Normal file
113
api/user.go
Normal file
|
@ -0,0 +1,113 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/drone/drone/cache"
|
||||
"github.com/drone/drone/model"
|
||||
"github.com/drone/drone/router/middleware/session"
|
||||
"github.com/drone/drone/shared/token"
|
||||
"github.com/drone/drone/store"
|
||||
)
|
||||
|
||||
// swagger:route GET /user user getUser
|
||||
//
|
||||
// Get the currently authenticated user.
|
||||
//
|
||||
// Responses:
|
||||
// 200: user
|
||||
//
|
||||
func GetSelf(c *gin.Context) {
|
||||
c.JSON(200, session.User(c))
|
||||
}
|
||||
|
||||
// swagger:route GET /user/feed user getUserFeed
|
||||
//
|
||||
// Get the currently authenticated user's build feed.
|
||||
//
|
||||
// Responses:
|
||||
// 200: feed
|
||||
//
|
||||
func GetFeed(c *gin.Context) {
|
||||
repos, err := cache.GetRepos(c, session.User(c))
|
||||
if err != nil {
|
||||
c.String(500, "Error fetching repository list. %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
feed, err := store.GetUserFeed(c, repos)
|
||||
if err != nil {
|
||||
c.String(500, "Error fetching feed. %s", err)
|
||||
return
|
||||
}
|
||||
c.JSON(200, feed)
|
||||
}
|
||||
|
||||
// swagger:route GET /user/repos user getUserRepos
|
||||
//
|
||||
// Get the currently authenticated user's active repository list.
|
||||
//
|
||||
// Responses:
|
||||
// 200: repos
|
||||
//
|
||||
func GetRepos(c *gin.Context) {
|
||||
repos, err := cache.GetRepos(c, session.User(c))
|
||||
if err != nil {
|
||||
c.String(500, "Error fetching repository list. %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
repos_, err := store.GetRepoListOf(c, repos)
|
||||
if err != nil {
|
||||
c.String(500, "Error fetching repository list. %s", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, repos_)
|
||||
}
|
||||
|
||||
func GetRemoteRepos(c *gin.Context) {
|
||||
repos, err := cache.GetRepos(c, session.User(c))
|
||||
if err != nil {
|
||||
c.String(500, "Error fetching repository list. %s", err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, repos)
|
||||
}
|
||||
|
||||
func PostToken(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
|
||||
token := token.New(token.UserToken, user.Login)
|
||||
tokenstr, err := token.Sign(user.Hash)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
c.String(http.StatusOK, tokenstr)
|
||||
}
|
||||
|
||||
// swagger:response user
|
||||
type userResp struct {
|
||||
// in: body
|
||||
Body model.User
|
||||
}
|
||||
|
||||
// swagger:response users
|
||||
type usersResp struct {
|
||||
// in: body
|
||||
Body []model.User
|
||||
}
|
||||
|
||||
// swagger:response feed
|
||||
type feedResp struct {
|
||||
// in: body
|
||||
Body []model.Feed
|
||||
}
|
||||
|
||||
// swagger:response repos
|
||||
type reposResp struct {
|
||||
// in: body
|
||||
Body []model.Repo
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controller
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -6,33 +6,43 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/drone/drone/model"
|
||||
"github.com/drone/drone/router/middleware/session"
|
||||
"github.com/drone/drone/shared/crypto"
|
||||
"github.com/drone/drone/store"
|
||||
)
|
||||
|
||||
// swagger:route GET /users user getUserList
|
||||
//
|
||||
// Get the list of all registered users.
|
||||
//
|
||||
// Responses:
|
||||
// 200: user
|
||||
//
|
||||
func GetUsers(c *gin.Context) {
|
||||
users, err := store.GetUserList(c)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
c.String(500, "Error getting user list. %s", err)
|
||||
} else {
|
||||
c.JSON(200, users)
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, users)
|
||||
}
|
||||
|
||||
// swagger:route GET /users/{login} user getUserLogin
|
||||
//
|
||||
// Get the user with the matching login.
|
||||
//
|
||||
// Responses:
|
||||
// 200: user
|
||||
//
|
||||
func GetUser(c *gin.Context) {
|
||||
user, err := store.GetUserLogin(c, c.Param("login"))
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
c.String(404, "Cannot find user. %s", err)
|
||||
} else {
|
||||
c.JSON(200, user)
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, user)
|
||||
}
|
||||
|
||||
func PatchUser(c *gin.Context) {
|
||||
me := session.User(c)
|
||||
in := &model.User{}
|
||||
err := c.Bind(in)
|
||||
if err != nil {
|
||||
|
@ -48,19 +58,13 @@ func PatchUser(c *gin.Context) {
|
|||
user.Admin = in.Admin
|
||||
user.Active = in.Active
|
||||
|
||||
// cannot update self
|
||||
if me.ID == user.ID {
|
||||
c.AbortWithStatus(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
err = store.UpdateUser(c, user)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, user)
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
|
||||
func PostUser(c *gin.Context) {
|
||||
|
@ -85,29 +89,25 @@ func PostUser(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, user)
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
|
||||
// swagger:route DELETE /users/{login} user deleteUserLogin
|
||||
//
|
||||
// Delete the user with the matching login.
|
||||
//
|
||||
// Responses:
|
||||
// 200: user
|
||||
//
|
||||
func DeleteUser(c *gin.Context) {
|
||||
me := session.User(c)
|
||||
|
||||
user, err := store.GetUserLogin(c, c.Param("login"))
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
c.String(404, "Cannot find user. %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// cannot delete self
|
||||
if me.ID == user.ID {
|
||||
c.AbortWithStatus(http.StatusForbidden)
|
||||
return
|
||||
if err = store.DeleteUser(c, user); err != nil {
|
||||
c.String(500, "Error deleting user. %s", err)
|
||||
} else {
|
||||
c.String(200, "")
|
||||
}
|
||||
|
||||
err = store.DeleteUser(c, user)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
c.Writer.WriteHeader(http.StatusNoContent)
|
||||
}
|
|
@ -231,10 +231,10 @@ func PostBuild(c *gin.Context) {
|
|||
|
||||
event := c.DefaultQuery("event", build.Event)
|
||||
if event == model.EventPush ||
|
||||
event == model.EventPull ||
|
||||
event == model.EventTag ||
|
||||
event == model.EventDeploy {
|
||||
build.Event = event
|
||||
event == model.EventPull ||
|
||||
event == model.EventTag ||
|
||||
event == model.EventDeploy {
|
||||
build.Event = event
|
||||
}
|
||||
build.Deploy = c.DefaultQuery("deploy_to", build.Deploy)
|
||||
}
|
||||
|
|
|
@ -200,3 +200,10 @@ func ShowBuild(c *gin.Context) {
|
|||
"Csrf": csrf,
|
||||
})
|
||||
}
|
||||
|
||||
func ShowNodes(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
nodes, _ := store.GetNodeList(c)
|
||||
token, _ := token.New(token.CsrfToken, user.Login).Sign(user.Hash)
|
||||
c.HTML(http.StatusOK, "nodes.html", gin.H{"User": user, "Nodes": nodes, "Csrf": token})
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/drone/drone/cache"
|
||||
"github.com/drone/drone/router/middleware/session"
|
||||
"github.com/drone/drone/shared/token"
|
||||
"github.com/drone/drone/store"
|
||||
)
|
||||
|
||||
func GetSelf(c *gin.Context) {
|
||||
c.IndentedJSON(200, session.User(c))
|
||||
}
|
||||
|
||||
func GetFeed(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
|
||||
// get the repository list from the cache
|
||||
repos, err := cache.GetRepos(c, user)
|
||||
if err != nil {
|
||||
c.String(400, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
feed, err := store.GetUserFeed(c, repos)
|
||||
if err != nil {
|
||||
c.String(400, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(200, feed)
|
||||
}
|
||||
|
||||
func GetRepos(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
|
||||
repos, err := cache.GetRepos(c, user)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// for each repository in the remote system we get
|
||||
// the intersection of those repostiories in Drone
|
||||
repos_, err := store.GetRepoListOf(c, repos)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, repos_)
|
||||
}
|
||||
|
||||
func GetRemoteRepos(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
|
||||
repos, err := cache.GetRepos(c, user)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
c.IndentedJSON(http.StatusOK, repos)
|
||||
}
|
||||
|
||||
func PostToken(c *gin.Context) {
|
||||
user := session.User(c)
|
||||
|
||||
token := token.New(token.UserToken, user.Login)
|
||||
tokenstr, err := token.Sign(user.Hash)
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
} else {
|
||||
c.String(http.StatusOK, tokenstr)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package model
|
||||
|
||||
// Feed represents an item in the user's feed or timeline.
|
||||
//
|
||||
// swagger:model feed
|
||||
type Feed struct {
|
||||
Owner string `json:"owner" meddler:"repo_owner"`
|
||||
Name string `json:"name" meddler:"repo_name"`
|
||||
|
|
|
@ -7,6 +7,9 @@ type RepoLite struct {
|
|||
Avatar string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
// Repo represents a repository.
|
||||
//
|
||||
// swagger:model repo
|
||||
type Repo struct {
|
||||
ID int64 `json:"id" meddler:"repo_id,pk"`
|
||||
UserID int64 `json:"-" meddler:"repo_user_id"`
|
||||
|
|
|
@ -1,14 +1,42 @@
|
|||
package model
|
||||
|
||||
// User represents a registered user.
|
||||
//
|
||||
// swagger:model user
|
||||
type User struct {
|
||||
ID int64 `json:"id" meddler:"user_id,pk"`
|
||||
Login string `json:"login" meddler:"user_login"`
|
||||
Token string `json:"-" meddler:"user_token"`
|
||||
Secret string `json:"-" meddler:"user_secret"`
|
||||
Expiry int64 `json:"-" meddler:"user_expiry"`
|
||||
Email string `json:"email" meddler:"user_email"`
|
||||
// the id for this user.
|
||||
//
|
||||
// required: true
|
||||
ID int64 `json:"id" meddler:"user_id,pk"`
|
||||
|
||||
// Login is the username for this user.
|
||||
//
|
||||
// required: true
|
||||
Login string `json:"login" meddler:"user_login"`
|
||||
|
||||
// Token is the oauth2 token.
|
||||
Token string `json:"-" meddler:"user_token"`
|
||||
|
||||
// Secret is the oauth2 token secret.
|
||||
Secret string `json:"-" meddler:"user_secret"`
|
||||
|
||||
// Expiry is the token and secret expriation timestamp.
|
||||
Expiry int64 `json:"-" meddler:"user_expiry"`
|
||||
|
||||
// Email is the email address for this user.
|
||||
//
|
||||
// required: true
|
||||
Email string `json:"email" meddler:"user_email"`
|
||||
|
||||
// the avatar url for this user.
|
||||
Avatar string `json:"avatar_url" meddler:"user_avatar"`
|
||||
Active bool `json:"active," meddler:"user_active"`
|
||||
Admin bool `json:"admin," meddler:"user_admin"`
|
||||
Hash string `json:"-" meddler:"user_hash"`
|
||||
|
||||
// Activate indicates the user is active in the system.
|
||||
Active bool `json:"active," meddler:"user_active"`
|
||||
|
||||
// Admin indicates the user is a system administrator.
|
||||
Admin bool `json:"admin," meddler:"user_admin"`
|
||||
|
||||
// Hash is a unique token used to sign tokens.
|
||||
Hash string `json:"-" meddler:"user_hash"`
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/drone/drone/api"
|
||||
"github.com/drone/drone/controller"
|
||||
"github.com/drone/drone/router/middleware/header"
|
||||
"github.com/drone/drone/router/middleware/location"
|
||||
|
@ -60,34 +61,34 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
|||
user := e.Group("/api/user")
|
||||
{
|
||||
user.Use(session.MustUser())
|
||||
user.GET("", controller.GetSelf)
|
||||
user.GET("/feed", controller.GetFeed)
|
||||
user.GET("/repos", controller.GetRepos)
|
||||
user.GET("/repos/remote", controller.GetRemoteRepos)
|
||||
user.POST("/token", controller.PostToken)
|
||||
user.GET("", api.GetSelf)
|
||||
user.GET("/feed", api.GetFeed)
|
||||
user.GET("/repos", api.GetRepos)
|
||||
user.GET("/repos/remote", api.GetRemoteRepos)
|
||||
user.POST("/token", api.PostToken)
|
||||
}
|
||||
|
||||
users := e.Group("/api/users")
|
||||
{
|
||||
users.Use(session.MustAdmin())
|
||||
users.GET("", controller.GetUsers)
|
||||
users.POST("", controller.PostUser)
|
||||
users.GET("/:login", controller.GetUser)
|
||||
users.PATCH("/:login", controller.PatchUser)
|
||||
users.DELETE("/:login", controller.DeleteUser)
|
||||
users.GET("", api.GetUsers)
|
||||
users.POST("", api.PostUser)
|
||||
users.GET("/:login", api.GetUser)
|
||||
users.PATCH("/:login", api.PatchUser)
|
||||
users.DELETE("/:login", api.DeleteUser)
|
||||
}
|
||||
|
||||
nodes := e.Group("/api/nodes")
|
||||
{
|
||||
nodes.Use(session.MustAdmin())
|
||||
nodes.GET("", controller.GetNodes)
|
||||
nodes.POST("", controller.PostNode)
|
||||
nodes.DELETE("/:node", controller.DeleteNode)
|
||||
nodes.GET("", api.GetNodes)
|
||||
nodes.POST("", api.PostNode)
|
||||
nodes.DELETE("/:node", api.DeleteNode)
|
||||
}
|
||||
|
||||
repos := e.Group("/api/repos/:owner/:name")
|
||||
{
|
||||
repos.POST("", controller.PostRepo)
|
||||
repos.POST("", api.PostRepo)
|
||||
|
||||
repo := repos.Group("")
|
||||
{
|
||||
|
@ -95,19 +96,19 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
|||
repo.Use(session.SetPerm())
|
||||
repo.Use(session.MustPull)
|
||||
|
||||
repo.GET("", controller.GetRepo)
|
||||
repo.GET("/key", controller.GetRepoKey)
|
||||
repo.POST("/key", controller.PostRepoKey)
|
||||
repo.GET("", api.GetRepo)
|
||||
repo.GET("/key", api.GetRepoKey)
|
||||
repo.POST("/key", api.PostRepoKey)
|
||||
repo.GET("/builds", controller.GetBuilds)
|
||||
repo.GET("/builds/:number", controller.GetBuild)
|
||||
repo.GET("/logs/:number/:job", controller.GetBuildLogs)
|
||||
|
||||
// requires authenticated user
|
||||
repo.POST("/encrypt", session.MustUser(), controller.PostSecure)
|
||||
repo.POST("/encrypt", session.MustUser(), api.PostSecure)
|
||||
|
||||
// requires push permissions
|
||||
repo.PATCH("", session.MustPush, controller.PatchRepo)
|
||||
repo.DELETE("", session.MustPush, controller.DeleteRepo)
|
||||
repo.PATCH("", session.MustPush, api.PatchRepo)
|
||||
repo.DELETE("", session.MustPush, api.DeleteRepo)
|
||||
|
||||
repo.POST("/builds/:number", session.MustPush, controller.PostBuild)
|
||||
repo.DELETE("/builds/:number/:job", session.MustPush, controller.DeleteBuild)
|
||||
|
|
Loading…
Reference in a new issue