some changes ;]]]]]

This commit is contained in:
Aleksander Cynarski 2020-01-15 20:40:53 +01:00
parent f24c030d8f
commit ab802985e9
12 changed files with 449 additions and 204 deletions

View File

@ -2,6 +2,7 @@ package controller
import (
"code.gitea.io/sdk/gitea"
"fmt"
"gitea-issue/giteaClient"
"gitea-issue/model"
"github.com/gin-gonic/gin"
@ -9,11 +10,11 @@ import (
"github.com/savaki/swag/swagger"
"net/http"
"strconv"
"fmt"
)
func PostIssue(c *gin.Context) {
var issueProxy model.PostCreateIssueProxy
if err := c.BindJSON(&issueProxy); err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
"message": "CREATE_ISSUE_ERROR",
@ -22,6 +23,10 @@ func PostIssue(c *gin.Context) {
return
}
sudo := c.GetHeader("X-Sudo")
if (sudo != "") {
giteaClient.SudoUser(sudo)
}
giteaIssue, err := issueProxy.TransformToGiteaCreateIssueOption()
if err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
@ -39,7 +44,7 @@ func PostIssue(c *gin.Context) {
})
return
}
c.AsciiJSON(http.StatusOK, response)
c.AsciiJSON(http.StatusOK, model.IssueTransformFromGitea(response))
}
func PostIssueSwagger() (*swagger.Endpoint) {
@ -48,7 +53,7 @@ func PostIssueSwagger() (*swagger.Endpoint){
endpoint.Description("Post new issue"),
endpoint.Body(model.PostCreateIssueProxy{}, "Issue object", true),
endpoint.Tags("issues"),
endpoint.Response(http.StatusOK, gitea.Issue{}, "Gitea Issue list"),
endpoint.Response(http.StatusOK, model.GetCreateIssueProxy{}, "Gitea Issue list"),
)
}
@ -70,6 +75,7 @@ func GetIssuesSwagger() (*swagger.Endpoint){
return endpoint.New("get", "/issues", "List project issues",
endpoint.Handler(GetIssues),
endpoint.Description("Get all issues"),
endpoint.Security("token", "USER"),
endpoint.Tags("issues"),
endpoint.Response(http.StatusOK, []model.GetCreateIssueProxy{}, "Gitea Issue list"),
)
@ -85,13 +91,14 @@ func GetIssue(c *gin.Context) {
if err != nil {
c.AbortWithStatus(http.StatusNotFound)
}
c.AsciiJSON(http.StatusOK, issue)
c.AsciiJSON(http.StatusOK, model.IssueTransformFromGitea(issue))
}
func GetIssueSwagger() (*swagger.Endpoint) {
return endpoint.New("get", "/issue/:id", "Get one issue",
return endpoint.New("get", "/issues/:id", "Get one issue",
endpoint.Handler(GetIssue),
endpoint.Description("Get one issue"),
endpoint.Security("token", "USER"),
endpoint.Tags("issues"),
endpoint.Response(http.StatusOK, model.GetCreateIssueProxy{}, "Gitea Issue"),
)
@ -104,6 +111,17 @@ func GetIssueComments(c *gin.Context) {
c.AsciiJSON(http.StatusNotFound, err.Error())
}
issueComments, err := giteaClient.GetIssueComments(issueId)
proxyComments := []model.GetCommentProxy{}
for _, comment := range issueComments {
proxyComments = append(proxyComments, model.CommentTransformFromGitea(comment))
}
if (err != nil) {
c.AbortWithStatus(http.StatusNotFound)
}
c.AsciiJSON(http.StatusOK, proxyComments)
if err != nil {
c.AbortWithStatus(http.StatusNotFound)
}
@ -111,10 +129,61 @@ func GetIssueComments(c *gin.Context) {
}
func GetIssueCommentsSwagger() (*swagger.Endpoint) {
return endpoint.New("get", "/issue/:id/comments", "Get issue comments",
endpoint.Handler(GetIssue),
return endpoint.New("get", "/issues/:id/comments", "Get issue comments",
endpoint.Handler(GetIssueComments),
endpoint.Description("Get issue comments"),
endpoint.Security("token", "USER"),
endpoint.Tags("issues"),
endpoint.Response(http.StatusOK, []gitea.Comment{}, "Gitea issue comments"),
)
}
func PostIssueComment(c *gin.Context) {
var commentProxy model.PostCommentProxy
if err := c.BindJSON(&commentProxy); err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
"message": "CREATE_COMMENT_ERROR",
"error": err.Error(),
})
return
}
issueId, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
fmt.Println(fmt.Sprintf("ParseInt err: %+v", err))
c.AsciiJSON(http.StatusNotFound, err.Error())
}
giteaComment, err := commentProxy.TransformToGiteaComment()
if err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
"message": "CREATE_COMMENT_ERROR",
"error": err.Error(),
})
return
}
sudo := c.GetHeader("X-Sudo")
if (sudo != "") {
giteaClient.SudoUser(sudo)
}
response, err := giteaClient.CreateComment(issueId, giteaComment)
if err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
"message": "CREATE_ISSUE_ERROR",
"error": err.Error(),
})
return
}
c.AsciiJSON(http.StatusOK, model.CommentTransformFromGitea(response))
}
func PostIssueCommentSwagger() (*swagger.Endpoint) {
return endpoint.New("post", "/issues/:id/comments", "Create issue comment",
endpoint.Handler(PostIssueComment),
endpoint.Description("Add issue comment"),
endpoint.Body(model.PostCommentProxy{}, "Comment object", true),
endpoint.Security("token", "USER"),
endpoint.Tags("issues"),
endpoint.Response(http.StatusOK, model.GetCommentProxy{}, "Gitea issue comments"),
)
}

42
controller/user.go Normal file
View File

@ -0,0 +1,42 @@
package controller
import (
"code.gitea.io/sdk/gitea"
"gitea-issue/giteaClient"
"gitea-issue/model"
"github.com/gin-gonic/gin"
"github.com/savaki/swag/endpoint"
"github.com/savaki/swag/swagger"
"net/http"
)
func PostUser(c *gin.Context) {
var userProxy model.PostUserProxy
if err := c.BindJSON(&userProxy); err != nil {
c.AsciiJSON(http.StatusBadRequest, gin.H{
"message": "CREATE_USER_ERROR",
"error": err.Error(),
})
return
}
response, err := giteaClient.CreateUser(userProxy.TransformToGiteaUser())
if err != nil {
c.AsciiJSON(http.StatusUnprocessableEntity, gin.H{
"message": "CREATE_USER_ERROR",
"error": err.Error(),
})
return
}
c.AsciiJSON(http.StatusOK, response)
}
func PostUserSwagger() (*swagger.Endpoint) {
return endpoint.New("post", "/user", "Create user",
endpoint.Handler(PostUser),
endpoint.Description("Post new user"),
endpoint.Body(model.PostUserProxy{}, "User object", true),
endpoint.Tags("user"),
endpoint.Response(http.StatusOK, gitea.User{}, "Gitea User"),
)
}

View File

@ -25,6 +25,10 @@ func GetUserInfo() (*gitea.User, error){
return usr, nil
}
func SudoUser(username string) {
giteaClient.SetSudo(username)
}
func GetServerInfo() (string, error) {
ver, err := giteaClient.ServerVersion()
if (err != nil) {
@ -33,10 +37,20 @@ func GetServerInfo() (string, error) {
return ver, nil
}
func CreateUser(user gitea.CreateUserOption) (*gitea.User, error) {
giteaUser, err := giteaClient.AdminCreateUser(user)
if (err != nil) {
fmt.Println(fmt.Sprintf("Gitea error: %+v", err.Error()))
return nil, err
}
return giteaUser, nil
}
func GetIssues() ([]*gitea.Issue, error) {
opt := gitea.ListIssueOption{
Page: 0,
State: "open",
State: "closed",
}
giteaIssues, err := giteaClient.ListRepoIssues(giteaOwner, giteaRepo, opt)
if (err != nil) {
@ -81,3 +95,13 @@ func CreateIssue(issue gitea.CreateIssueOption) (*gitea.Issue, error){
}
return giteaCreateIssue, nil
}
func CreateComment(id int64, option gitea.CreateIssueCommentOption) (*gitea.Comment, error) {
giteaComment, err := giteaClient.CreateIssueComment(giteaOwner, giteaRepo, id, option)
if (err != nil) {
fmt.Println(fmt.Sprintf("Gitea create comment error: %+v", err.Error()))
return nil, err
}
return giteaComment, nil
}

46
main.go
View File

@ -4,37 +4,27 @@ import (
"fmt"
"gitea-issue/controller"
"gitea-issue/giteaClient"
"gitea-issue/proxy"
"gitea-issue/security"
"github.com/caarlos0/env"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/savaki/swag"
"github.com/savaki/swag/swagger"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
"net/http"
"strconv"
"github.com/savaki/swag"
"github.com/savaki/swag/swagger"
)
var (
db *gorm.DB
giteaConfig giteaClient.GiteaConfig
proxyConfig ProxyConfig
proxyConfig proxy.ProxyConfig
)
type ProxyConfig struct {
ProjectOrigin string `env:"PROJECT_ORIGIN,required"`
}
func init() {
//open a db connection
var err error
db, err := gorm.Open("sqlite3", "./database.db")
if err != nil {
panic("failed to connect database")
}
if err := env.Parse(&giteaConfig); err != nil {
panic(fmt.Sprintf("ENV error: %+v", err.Error()))
}
@ -43,7 +33,8 @@ func init() {
}
giteaClient.SetUp(giteaConfig)
db.AutoMigrate(&userModel{})
proxy.SetUp(proxyConfig)
}
func main() {
@ -53,6 +44,7 @@ func main() {
config.AllowOrigins = []string{proxyConfig.ProjectOrigin}
router.Use(gin.Logger())
router.Use(cors.New(config))
router.Use(gin.Recovery())
proxyApi := swag.New(
swag.Title("Gitea issues proxy"),
@ -62,34 +54,31 @@ func main() {
swag.Tag("issues", "Gitea issues proxy endpoints"),
swag.Tag("labels", "Gites labels for issue"),
swag.Endpoints(
controller.PostUserSwagger(),
controller.PostIssueSwagger(),
controller.PostIssueCommentSwagger(),
controller.GetIssuesSwagger(),
controller.GetIssueSwagger(),
controller.GetIssueCommentsSwagger(),
controller.GetLabelsSwagger()),
)
authorizedApi := router.Group("/", security.BearerToken())
proxyApi.Walk(func(path string, endpoint *swagger.Endpoint) {
h := endpoint.Handler.(func(c *gin.Context))
path = swag.ColonPath(path)
router.Handle(endpoint.Method, path, h)
authorizedApi.Handle(endpoint.Method, path, h)
})
router.GET("/swagger.json", gin.WrapH(proxyApi.Handler(true)))
docs := router.Group("/")
docs.GET("/swagger.json", gin.WrapH(proxyApi.Handler(true)))
url := ginSwagger.URL("/swagger.json")
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
docs.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
_ = router.Run()
}
type (
userModel struct {
gorm.Model
Email string `json:"email"`
Token int `json:"token"`
}
)
func getIssues(c *gin.Context) {
issues, err := giteaClient.GetIssues();
if (err != nil) {
@ -131,4 +120,3 @@ func getLabels(c *gin.Context) {
}
c.AsciiJSON(http.StatusOK, labels)
}

35
model/commentProxy.go Normal file
View File

@ -0,0 +1,35 @@
package model
import (
"code.gitea.io/sdk/gitea"
"time"
)
type GetCommentProxy struct {
Id int64 `json:"id"`
Body string `json:"body"`
OriginalAuthor string `json:"original_author"`
CreatedAt time.Time `json:"created_at"`
}
type PostCommentProxy struct {
Body string `json:"body"`
}
func (c PostCommentProxy) TransformToGiteaComment() (gitea.CreateIssueCommentOption, error) {
giteaObject := gitea.CreateIssueCommentOption{
Body: c.Body,
}
return giteaObject, nil
}
func CommentTransformFromGitea(comment *gitea.Comment) (GetCommentProxy) {
giteaComment := GetCommentProxy{
Id: comment.ID,
Body: comment.Body,
OriginalAuthor: comment.OriginalAuthor,
CreatedAt: comment.Created,
}
return giteaComment
}

View File

@ -7,6 +7,7 @@ import (
)
type GetCreateIssueProxy struct {
Id int64 `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
Labels []*gitea.Label `json:"labels"`
@ -43,6 +44,7 @@ func (c PostCreateIssueProxy) TransformToGiteaCreateIssueOption() (gitea.CreateI
func IssueTransformFromGitea(issue *gitea.Issue) (GetCreateIssueProxy) {
giteaIssue := GetCreateIssueProxy{
Id: issue.Index,
Title: issue.Title,
Body: issue.Body,
Labels: issue.Labels,

47
model/userProxy.go Normal file
View File

@ -0,0 +1,47 @@
package model
import (
"code.gitea.io/sdk/gitea"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
"math/rand"
"unicode"
)
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456!@#$%")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
type PostUserProxy struct {
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
func isMn(r rune) bool {
return unicode.Is(unicode.Mn, r)
}
func (c PostUserProxy) TransformToGiteaUser() (gitea.CreateUserOption) {
t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
username, _, _ := transform.String(t, c.FirstName+c.LastName)
giteaObject := gitea.CreateUserOption{
SourceID: 0,
LoginName: c.Email,
Username: username,
FullName: c.FirstName + " " + c.LastName,
Email: c.Email,
Password: randSeq(12),
MustChangePassword: nil,
SendNotify: false,
}
return giteaObject
}

9
proxy/proxyClient.go Normal file
View File

@ -0,0 +1,9 @@
package proxy
var (
Bearer string
)
func SetUp(config ProxyConfig) {
Bearer = config.ProxyToken
}

6
proxy/proxyConfig.go Normal file
View File

@ -0,0 +1,6 @@
package proxy
type ProxyConfig struct {
ProjectOrigin string `env:"PROJECT_ORIGIN,required"`
ProxyToken string `env:"PROXY_TOKEN,required"`
}

View File

@ -0,0 +1,23 @@
package security
import (
"gitea-issue/proxy"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func BearerToken() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if (token == "") {
c.AbortWithStatus(http.StatusBadRequest)
}
var tokenArr []string
tokenArr = strings.Split(token, " ")
if (tokenArr[1] != proxy.Bearer) {
c.AbortWithStatus(http.StatusUnauthorized)
}
c.Next()
}
}