219 lines
5.3 KiB
Go
219 lines
5.3 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/heicode/manager/common"
|
|
"github.com/heicode/manager/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type gitSourcePayload struct {
|
|
Name string `json:"name"`
|
|
Provider string `json:"provider"`
|
|
RepoURL string `json:"repo_url"`
|
|
Ref string `json:"ref"`
|
|
Paths []string `json:"paths"`
|
|
Usage string `json:"usage"`
|
|
TenantId string `json:"tenant_id"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
type gitSourceResponse struct {
|
|
Id int `json:"id"`
|
|
UserId int `json:"user_id"`
|
|
TenantId string `json:"tenant_id"`
|
|
Name string `json:"name"`
|
|
Provider string `json:"provider"`
|
|
RepoURL string `json:"repo_url"`
|
|
Ref string `json:"ref"`
|
|
Paths []string `json:"paths"`
|
|
Usage string `json:"usage"`
|
|
Status string `json:"status"`
|
|
CreatedAt int64 `json:"created_at"`
|
|
UpdatedAt int64 `json:"updated_at"`
|
|
}
|
|
|
|
func normalizeGitSourcePayload(p gitSourcePayload) (gitSourcePayload, error) {
|
|
p.Name = strings.TrimSpace(p.Name)
|
|
p.Provider = strings.TrimSpace(p.Provider)
|
|
p.RepoURL = strings.TrimSpace(p.RepoURL)
|
|
p.Ref = strings.TrimSpace(p.Ref)
|
|
p.Usage = strings.TrimSpace(p.Usage)
|
|
p.TenantId = strings.TrimSpace(p.TenantId)
|
|
p.Status = strings.TrimSpace(p.Status)
|
|
|
|
if p.Name == "" {
|
|
return p, errors.New("name required")
|
|
}
|
|
if p.RepoURL == "" {
|
|
return p, errors.New("repo_url required")
|
|
}
|
|
u, err := url.Parse(p.RepoURL)
|
|
if err != nil || u.Scheme == "" || u.Host == "" {
|
|
return p, errors.New("repo_url must be a valid http(s) URL")
|
|
}
|
|
if p.Ref == "" {
|
|
p.Ref = "main"
|
|
}
|
|
if p.Provider == "" {
|
|
p.Provider = "custom"
|
|
}
|
|
if p.Usage == "" {
|
|
p.Usage = "project"
|
|
}
|
|
if p.Status == "" {
|
|
p.Status = "active"
|
|
}
|
|
|
|
paths := make([]string, 0, len(p.Paths))
|
|
for _, path := range p.Paths {
|
|
path = strings.TrimSpace(path)
|
|
if path == "" {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(path, "/") || strings.Contains(path, "..") {
|
|
return p, errors.New("paths must be relative and must not contain ..")
|
|
}
|
|
paths = append(paths, path)
|
|
}
|
|
if len(paths) == 0 {
|
|
paths = []string{"."}
|
|
}
|
|
p.Paths = paths
|
|
return p, nil
|
|
}
|
|
|
|
func gitSourceToResponse(src model.GitSource) gitSourceResponse {
|
|
var paths []string
|
|
if src.Paths != "" {
|
|
_ = common.UnmarshalJsonStr(src.Paths, &paths)
|
|
}
|
|
if len(paths) == 0 {
|
|
paths = []string{"."}
|
|
}
|
|
return gitSourceResponse{
|
|
Id: src.Id,
|
|
UserId: src.UserId,
|
|
TenantId: src.TenantId,
|
|
Name: src.Name,
|
|
Provider: src.Provider,
|
|
RepoURL: src.RepoURL,
|
|
Ref: src.Ref,
|
|
Paths: paths,
|
|
Usage: src.Usage,
|
|
Status: src.Status,
|
|
CreatedAt: src.CreatedAt,
|
|
UpdatedAt: src.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
func ListGitSources(c *gin.Context) {
|
|
userId := c.GetInt("id")
|
|
var sources []model.GitSource
|
|
if err := model.DB.Where("user_id = ?", userId).Order("id desc").Find(&sources).Error; err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
items := make([]gitSourceResponse, 0, len(sources))
|
|
for _, src := range sources {
|
|
items = append(items, gitSourceToResponse(src))
|
|
}
|
|
common.ApiSuccess(c, gin.H{"items": items})
|
|
}
|
|
|
|
func CreateGitSource(c *gin.Context) {
|
|
userId := c.GetInt("id")
|
|
var payload gitSourcePayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "message": "invalid params"})
|
|
return
|
|
}
|
|
payload, err := normalizeGitSourcePayload(payload)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
paths, err := common.Marshal(payload.Paths)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
src := model.GitSource{
|
|
UserId: userId,
|
|
TenantId: payload.TenantId,
|
|
Name: payload.Name,
|
|
Provider: payload.Provider,
|
|
RepoURL: payload.RepoURL,
|
|
Ref: payload.Ref,
|
|
Paths: string(paths),
|
|
Usage: payload.Usage,
|
|
Status: payload.Status,
|
|
}
|
|
if err := model.DB.Create(&src).Error; err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, gitSourceToResponse(src))
|
|
}
|
|
|
|
func UpdateGitSource(c *gin.Context) {
|
|
userId := c.GetInt("id")
|
|
var src model.GitSource
|
|
if err := model.DB.Where("id = ? AND user_id = ?", c.Param("id"), userId).First(&src).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
common.ApiErrorMsg(c, "git source not found")
|
|
return
|
|
}
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
var payload gitSourcePayload
|
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"success": false, "message": "invalid params"})
|
|
return
|
|
}
|
|
payload, err := normalizeGitSourcePayload(payload)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
paths, err := common.Marshal(payload.Paths)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
src.TenantId = payload.TenantId
|
|
src.Name = payload.Name
|
|
src.Provider = payload.Provider
|
|
src.RepoURL = payload.RepoURL
|
|
src.Ref = payload.Ref
|
|
src.Paths = string(paths)
|
|
src.Usage = payload.Usage
|
|
src.Status = payload.Status
|
|
if err := model.DB.Save(&src).Error; err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, gitSourceToResponse(src))
|
|
}
|
|
|
|
func DeleteGitSource(c *gin.Context) {
|
|
userId := c.GetInt("id")
|
|
res := model.DB.Where("id = ? AND user_id = ?", c.Param("id"), userId).Delete(&model.GitSource{})
|
|
if res.Error != nil {
|
|
common.ApiError(c, res.Error)
|
|
return
|
|
}
|
|
if res.RowsAffected == 0 {
|
|
common.ApiErrorMsg(c, "git source not found")
|
|
return
|
|
}
|
|
common.ApiSuccess(c, gin.H{"deleted": true})
|
|
}
|