From ab802985e93a18fa3b3fb6a6a7ba8ed579b08b4a Mon Sep 17 00:00:00 2001 From: Aleksander Cynarski Date: Wed, 15 Jan 2020 20:40:53 +0100 Subject: [PATCH] some changes ;]]]]] --- Godeps/Godeps.json | 256 ++++++++++++++++++------------------ controller/issue.go | 93 +++++++++++-- controller/label.go | 4 +- controller/user.go | 42 ++++++ giteaClient/giteaClient.go | 56 +++++--- main.go | 48 +++---- model/commentProxy.go | 35 +++++ model/issueProxy.go | 34 ++--- model/userProxy.go | 47 +++++++ proxy/proxyClient.go | 9 ++ proxy/proxyConfig.go | 6 + security/tokenMiddleware.go | 23 ++++ 12 files changed, 449 insertions(+), 204 deletions(-) create mode 100644 controller/user.go create mode 100644 model/commentProxy.go create mode 100644 model/userProxy.go create mode 100644 proxy/proxyClient.go create mode 100644 proxy/proxyConfig.go create mode 100644 security/tokenMiddleware.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index ac8be44..6c576f7 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,130 +1,130 @@ { - "ImportPath": "gitea-issue", - "GoVersion": "go1.13", - "GodepVersion": "v80", - "Deps": [ - { - "ImportPath": "code.gitea.io/sdk/gitea", - "Rev": "b374d7ccc4b455f1e1829ab3ff0808de80bc39e0" - }, - { - "ImportPath": "github.com/caarlos0/env", - "Comment": "v6.1.0-4-g6cef6a7", - "Rev": "6cef6a7f8b01a4288118f1a4c5c303f117c1c7f0" - }, - { - "ImportPath": "github.com/gin-contrib/cors", - "Comment": "v1.3.0-1-g2a8f489", - "Rev": "2a8f489b42294786cbf465c1f20588b49117f1fe" - }, - { - "ImportPath": "github.com/gin-contrib/sse", - "Comment": "v0.1.0-1-g43f0f29", - "Rev": "43f0f29dbd2b3f0feeebff91fd9cda22db296938" - }, - { - "ImportPath": "github.com/gin-gonic/gin", - "Comment": "v1.4.0-57-g517eacb", - "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" - }, - { - "ImportPath": "github.com/gin-gonic/gin/binding", - "Comment": "v1.4.0-57-g517eacb", - "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" - }, - { - "ImportPath": "github.com/gin-gonic/gin/internal/json", - "Comment": "v1.4.0-57-g517eacb", - "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" - }, - { - "ImportPath": "github.com/gin-gonic/gin/render", - "Comment": "v1.4.0-57-g517eacb", - "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" - }, - { - "ImportPath": "github.com/go-playground/locales", - "Comment": "v0.13.0", - "Rev": "9f105231d3a5f6877a2bf8321dfa15ea6f844b1b" - }, - { - "ImportPath": "github.com/go-playground/locales/currency", - "Comment": "v0.13.0", - "Rev": "9f105231d3a5f6877a2bf8321dfa15ea6f844b1b" - }, - { - "ImportPath": "github.com/go-playground/universal-translator", - "Comment": "v0.16.0-1-g7120149", - "Rev": "71201497bace774495daed26a3874fd339e0b538" - }, - { - "ImportPath": "github.com/golang/protobuf/proto", - "Comment": "v1.3.2-4-ged6926b3", - "Rev": "ed6926b37a637426117ccab59282c3839528a700" - }, - { - "ImportPath": "github.com/jinzhu/gorm", - "Comment": "v1.9.11-20-g179760d", - "Rev": "179760d8343ed15cbb9f071ca824bc35ee7784bb" - }, - { - "ImportPath": "github.com/jinzhu/gorm/dialects/sqlite", - "Comment": "v1.9.11-20-g179760d", - "Rev": "179760d8343ed15cbb9f071ca824bc35ee7784bb" - }, - { - "ImportPath": "github.com/jinzhu/inflection", - "Comment": "v1.0.0", - "Rev": "f5c5f50e6090ae76a29240b61ae2a90dd810112e" - }, - { - "ImportPath": "github.com/json-iterator/go", - "Comment": "1.1.8-2-gdc11f49", - "Rev": "dc11f49689fd1c9a6de20749def70bd889bf0d42" - }, - { - "ImportPath": "github.com/leodido/go-urn", - "Comment": "v1.2.0", - "Rev": "a0f5013415294bb94553821ace21a1a74c0298cc" - }, - { - "ImportPath": "github.com/mattn/go-isatty", - "Comment": "v0.0.10-1-g0e9ddb7", - "Rev": "0e9ddb7c0c0aef74fa25eaba4141e6b5ab7aca2a" - }, - { - "ImportPath": "github.com/mattn/go-sqlite3", - "Comment": "v1.11.0-15-g3f45aef", - "Rev": "3f45aefa8dc8bbdd97619dd2765f864972f3310e" - }, - { - "ImportPath": "github.com/modern-go/concurrent", - "Comment": "1.0.3", - "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" - }, - { - "ImportPath": "github.com/modern-go/reflect2", - "Comment": "v1.0.1", - "Rev": "94122c33edd36123c84d5368cfb2b69df93a0ec8" - }, - { - "ImportPath": "github.com/ugorji/go/codec", - "Comment": "codec/codecgen/v1.1.7-29-g42bc974", - "Rev": "42bc974514ff101a54c6b72a0e4dee29d96c0b26" - }, - { - "ImportPath": "golang.org/x/sys/unix", - "Rev": "f43be2a4598cf3a47be9f94f0c28197ed9eae611" - }, - { - "ImportPath": "gopkg.in/go-playground/validator.v9", - "Comment": "v9.30.0", - "Rev": "cd1bd581694a11c089aea885a26247c5f783a4cf" - }, - { - "ImportPath": "gopkg.in/yaml.v2", - "Comment": "v2.2.4", - "Rev": "f221b8435cfb71e54062f6c6e99e9ade30b124d5" - } - ] + "ImportPath": "gitea-issue", + "GoVersion": "go1.13", + "GodepVersion": "v80", + "Deps": [ + { + "ImportPath": "code.gitea.io/sdk/gitea", + "Rev": "b374d7ccc4b455f1e1829ab3ff0808de80bc39e0" + }, + { + "ImportPath": "github.com/caarlos0/env", + "Comment": "v6.1.0-4-g6cef6a7", + "Rev": "6cef6a7f8b01a4288118f1a4c5c303f117c1c7f0" + }, + { + "ImportPath": "github.com/gin-contrib/cors", + "Comment": "v1.3.0-1-g2a8f489", + "Rev": "2a8f489b42294786cbf465c1f20588b49117f1fe" + }, + { + "ImportPath": "github.com/gin-contrib/sse", + "Comment": "v0.1.0-1-g43f0f29", + "Rev": "43f0f29dbd2b3f0feeebff91fd9cda22db296938" + }, + { + "ImportPath": "github.com/gin-gonic/gin", + "Comment": "v1.4.0-57-g517eacb", + "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" + }, + { + "ImportPath": "github.com/gin-gonic/gin/binding", + "Comment": "v1.4.0-57-g517eacb", + "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" + }, + { + "ImportPath": "github.com/gin-gonic/gin/internal/json", + "Comment": "v1.4.0-57-g517eacb", + "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" + }, + { + "ImportPath": "github.com/gin-gonic/gin/render", + "Comment": "v1.4.0-57-g517eacb", + "Rev": "517eacb4f9ca7276511841c63e2911d6ec94c22a" + }, + { + "ImportPath": "github.com/go-playground/locales", + "Comment": "v0.13.0", + "Rev": "9f105231d3a5f6877a2bf8321dfa15ea6f844b1b" + }, + { + "ImportPath": "github.com/go-playground/locales/currency", + "Comment": "v0.13.0", + "Rev": "9f105231d3a5f6877a2bf8321dfa15ea6f844b1b" + }, + { + "ImportPath": "github.com/go-playground/universal-translator", + "Comment": "v0.16.0-1-g7120149", + "Rev": "71201497bace774495daed26a3874fd339e0b538" + }, + { + "ImportPath": "github.com/golang/protobuf/proto", + "Comment": "v1.3.2-4-ged6926b3", + "Rev": "ed6926b37a637426117ccab59282c3839528a700" + }, + { + "ImportPath": "github.com/jinzhu/gorm", + "Comment": "v1.9.11-20-g179760d", + "Rev": "179760d8343ed15cbb9f071ca824bc35ee7784bb" + }, + { + "ImportPath": "github.com/jinzhu/gorm/dialects/sqlite", + "Comment": "v1.9.11-20-g179760d", + "Rev": "179760d8343ed15cbb9f071ca824bc35ee7784bb" + }, + { + "ImportPath": "github.com/jinzhu/inflection", + "Comment": "v1.0.0", + "Rev": "f5c5f50e6090ae76a29240b61ae2a90dd810112e" + }, + { + "ImportPath": "github.com/json-iterator/go", + "Comment": "1.1.8-2-gdc11f49", + "Rev": "dc11f49689fd1c9a6de20749def70bd889bf0d42" + }, + { + "ImportPath": "github.com/leodido/go-urn", + "Comment": "v1.2.0", + "Rev": "a0f5013415294bb94553821ace21a1a74c0298cc" + }, + { + "ImportPath": "github.com/mattn/go-isatty", + "Comment": "v0.0.10-1-g0e9ddb7", + "Rev": "0e9ddb7c0c0aef74fa25eaba4141e6b5ab7aca2a" + }, + { + "ImportPath": "github.com/mattn/go-sqlite3", + "Comment": "v1.11.0-15-g3f45aef", + "Rev": "3f45aefa8dc8bbdd97619dd2765f864972f3310e" + }, + { + "ImportPath": "github.com/modern-go/concurrent", + "Comment": "1.0.3", + "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + }, + { + "ImportPath": "github.com/modern-go/reflect2", + "Comment": "v1.0.1", + "Rev": "94122c33edd36123c84d5368cfb2b69df93a0ec8" + }, + { + "ImportPath": "github.com/ugorji/go/codec", + "Comment": "codec/codecgen/v1.1.7-29-g42bc974", + "Rev": "42bc974514ff101a54c6b72a0e4dee29d96c0b26" + }, + { + "ImportPath": "golang.org/x/sys/unix", + "Rev": "f43be2a4598cf3a47be9f94f0c28197ed9eae611" + }, + { + "ImportPath": "gopkg.in/go-playground/validator.v9", + "Comment": "v9.30.0", + "Rev": "cd1bd581694a11c089aea885a26247c5f783a4cf" + }, + { + "ImportPath": "gopkg.in/yaml.v2", + "Comment": "v2.2.4", + "Rev": "f221b8435cfb71e54062f6c6e99e9ade30b124d5" + } + ] } diff --git a/controller/issue.go b/controller/issue.go index 122b666..e0b04f0 100644 --- a/controller/issue.go +++ b/controller/issue.go @@ -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,16 +44,16 @@ func PostIssue(c *gin.Context) { }) return } - c.AsciiJSON(http.StatusOK, response) + c.AsciiJSON(http.StatusOK, model.IssueTransformFromGitea(response)) } -func PostIssueSwagger() (*swagger.Endpoint){ +func PostIssueSwagger() (*swagger.Endpoint) { return endpoint.New("post", "/issues", "Create issue", endpoint.Handler(PostIssue), 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"), ) } @@ -60,16 +65,17 @@ func GetIssues(c *gin.Context) { proxyIssues = append(proxyIssues, model.IssueTransformFromGitea(issue)) } - if(err != nil){ + if (err != nil) { c.AbortWithStatus(http.StatusNotFound) } c.AsciiJSON(http.StatusOK, proxyIssues) } -func GetIssuesSwagger() (*swagger.Endpoint){ +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", +func GetIssueSwagger() (*swagger.Endpoint) { + 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,17 +111,79 @@ 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) } c.AsciiJSON(http.StatusOK, issueComments) } -func GetIssueCommentsSwagger() (*swagger.Endpoint){ - return endpoint.New("get", "/issue/:id/comments", "Get issue comments", - endpoint.Handler(GetIssue), +func GetIssueCommentsSwagger() (*swagger.Endpoint) { + 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"), + ) +} diff --git a/controller/label.go b/controller/label.go index 7548b87..31d398a 100644 --- a/controller/label.go +++ b/controller/label.go @@ -17,11 +17,11 @@ func GetLabels(c *gin.Context) { c.AsciiJSON(http.StatusOK, labels) } -func GetLabelsSwagger() (*swagger.Endpoint){ +func GetLabelsSwagger() (*swagger.Endpoint) { return endpoint.New("get", "/labels", "List project labels", endpoint.Handler(GetLabels), endpoint.Description("Get all labels"), endpoint.Tags("labels"), endpoint.Response(http.StatusOK, []gitea.Label{}, "Gitea labels list"), ) -} \ No newline at end of file +} diff --git a/controller/user.go b/controller/user.go new file mode 100644 index 0000000..b7fafcf --- /dev/null +++ b/controller/user.go @@ -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"), + ) +} diff --git a/giteaClient/giteaClient.go b/giteaClient/giteaClient.go index ac02ad6..3078819 100644 --- a/giteaClient/giteaClient.go +++ b/giteaClient/giteaClient.go @@ -5,41 +5,55 @@ import ( "fmt" ) -var( +var ( giteaClient *gitea.Client - giteaOwner string - giteaRepo string + giteaOwner string + giteaRepo string ) -func SetUp(config GiteaConfig){ +func SetUp(config GiteaConfig) { giteaClient = gitea.NewClient(config.GiteaUrl, config.GiteaToken) giteaOwner = config.GiteaOwner giteaRepo = config.GiteaRepo } -func GetUserInfo() (*gitea.User, error){ +func GetUserInfo() (*gitea.User, error) { usr, err := giteaClient.GetMyUserInfo() - if(err != nil){ + if (err != nil) { return nil, err } return usr, nil } +func SudoUser(username string) { + giteaClient.SetSudo(username) +} + func GetServerInfo() (string, error) { ver, err := giteaClient.ServerVersion() - if(err != nil){ + if (err != nil) { return "", err } return ver, nil } -func GetIssues() ([]*gitea.Issue, error){ +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){ + if (err != nil) { fmt.Println(fmt.Sprintf("Gitea error: %+v", err.Error())) return nil, err } @@ -48,7 +62,7 @@ func GetIssues() ([]*gitea.Issue, error){ func GetIssue(issueID int64) (*gitea.Issue, error) { giteaIssue, err := giteaClient.GetIssue(giteaOwner, giteaRepo, issueID) - if( err != nil){ + if (err != nil) { fmt.Println(fmt.Sprintf("GetIssue gitea error: %+v", err.Error())) return nil, err } @@ -57,7 +71,7 @@ func GetIssue(issueID int64) (*gitea.Issue, error) { func GetIssueComments(issueID int64) ([]*gitea.Comment, error) { giteaIssueComments, err := giteaClient.ListIssueComments(giteaOwner, giteaRepo, issueID) - if( err != nil){ + if (err != nil) { fmt.Println(fmt.Sprintf("Gitea get isse comments error: %+v", err.Error())) return nil, err } @@ -66,18 +80,28 @@ func GetIssueComments(issueID int64) ([]*gitea.Comment, error) { func GetLabels() ([]*gitea.Label, error) { giteaLabels, err := giteaClient.ListRepoLabels(giteaOwner, giteaRepo) - if( err != nil){ + if (err != nil) { fmt.Println(fmt.Sprintf("Gitea get labels error: %+v", err.Error())) return nil, err } return giteaLabels, nil } -func CreateIssue(issue gitea.CreateIssueOption) (*gitea.Issue, error){ +func CreateIssue(issue gitea.CreateIssueOption) (*gitea.Issue, error) { giteaCreateIssue, err := giteaClient.CreateIssue(giteaOwner, giteaRepo, issue) - if( err != nil){ + if (err != nil) { fmt.Println(fmt.Sprintf("Gitea get labels error: %+v", err.Error())) return nil, err } return giteaCreateIssue, nil -} \ No newline at end of file +} + +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 + +} diff --git a/main.go b/main.go index caca35c..2d96b10 100644 --- a/main.go +++ b/main.go @@ -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,37 +54,34 @@ 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){ + if (err != nil) { c.AbortWithStatus(http.StatusNotFound) } c.AsciiJSON(http.StatusOK, issues) @@ -131,4 +120,3 @@ func getLabels(c *gin.Context) { } c.AsciiJSON(http.StatusOK, labels) } - diff --git a/model/commentProxy.go b/model/commentProxy.go new file mode 100644 index 0000000..def69f3 --- /dev/null +++ b/model/commentProxy.go @@ -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 +} diff --git a/model/issueProxy.go b/model/issueProxy.go index 6364b1f..46f5011 100644 --- a/model/issueProxy.go +++ b/model/issueProxy.go @@ -7,34 +7,35 @@ import ( ) type GetCreateIssueProxy struct { - Title string `json:"title"` - Body string `json:"body"` - Labels []*gitea.Label `json:"labels"` - Closed *time.Time `json:"closed"` + Id int64 `json:"id"` + Title string `json:"title"` + Body string `json:"body"` + Labels []*gitea.Label `json:"labels"` + Closed *time.Time `json:"closed"` } type PostCreateIssueProxy struct { - Title string `json:"title"` - Body string `json:"body"` + Title string `json:"title"` + Body string `json:"body"` Labels []*gitea.Label `json:"labels"` } -func (c PostCreateIssueProxy) TransformToGiteaCreateIssueOption() (gitea.CreateIssueOption, error){ +func (c PostCreateIssueProxy) TransformToGiteaCreateIssueOption() (gitea.CreateIssueOption, error) { giteaUser, err := giteaClient.GetUserInfo() - if( err != nil){ - return gitea.CreateIssueOption{}, err; + if (err != nil) { + return gitea.CreateIssueOption{}, err; } labels := []int64{} - for _, label := range c.Labels{ + for _, label := range c.Labels { labels = append(labels, label.ID) } giteaObject := gitea.CreateIssueOption{ - Title: c.Title, - Body: c.Body, - Assignee: giteaUser.UserName, - Labels: labels, - Closed: false, + Title: c.Title, + Body: c.Body, + Assignee: giteaUser.UserName, + Labels: labels, + Closed: false, } return giteaObject, nil @@ -43,10 +44,11 @@ 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, Closed: issue.Closed, } return giteaIssue -} \ No newline at end of file +} diff --git a/model/userProxy.go b/model/userProxy.go new file mode 100644 index 0000000..987b7b2 --- /dev/null +++ b/model/userProxy.go @@ -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 +} diff --git a/proxy/proxyClient.go b/proxy/proxyClient.go new file mode 100644 index 0000000..18fc273 --- /dev/null +++ b/proxy/proxyClient.go @@ -0,0 +1,9 @@ +package proxy + +var ( + Bearer string +) + +func SetUp(config ProxyConfig) { + Bearer = config.ProxyToken +} diff --git a/proxy/proxyConfig.go b/proxy/proxyConfig.go new file mode 100644 index 0000000..c02ac56 --- /dev/null +++ b/proxy/proxyConfig.go @@ -0,0 +1,6 @@ +package proxy + +type ProxyConfig struct { + ProjectOrigin string `env:"PROJECT_ORIGIN,required"` + ProxyToken string `env:"PROXY_TOKEN,required"` +} diff --git a/security/tokenMiddleware.go b/security/tokenMiddleware.go new file mode 100644 index 0000000..a25b9d5 --- /dev/null +++ b/security/tokenMiddleware.go @@ -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() + } +}