mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-07-06 16:11:56 +08:00
路由、权限相关接口完成
This commit is contained in:
@@ -1,33 +1,33 @@
|
||||
package api
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/APIParkLab/APIPark/module/api"
|
||||
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
api_dto "github.com/APIParkLab/APIPark/module/api/dto"
|
||||
"github.com/APIParkLab/APIPark/module/router"
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
)
|
||||
|
||||
var _ IAPIController = (*imlAPIController)(nil)
|
||||
var _ IRouterController = (*imlAPIController)(nil)
|
||||
|
||||
type imlAPIController struct {
|
||||
module api.IApiModule `autowired:""`
|
||||
module router.IRouterModule `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) {
|
||||
func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) {
|
||||
return i.module.Detail(ctx, serviceId, apiId)
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Search(ctx *gin.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) {
|
||||
func (i *imlAPIController) Search(ctx *gin.Context, keyword string, serviceId string) ([]*router_dto.Item, error) {
|
||||
return i.module.Search(ctx, keyword, serviceId)
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) {
|
||||
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) {
|
||||
return i.module.Create(ctx, serviceId, dto)
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) {
|
||||
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) {
|
||||
return i.module.Edit(ctx, serviceId, apiId, dto)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package router
|
||||
|
||||
import (
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
@@ -8,18 +8,18 @@ import (
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
api_dto "github.com/APIParkLab/APIPark/module/api/dto"
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
)
|
||||
|
||||
type IAPIController interface {
|
||||
type IRouterController interface {
|
||||
// Detail 获取API详情
|
||||
Detail(ctx *gin.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error)
|
||||
Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error)
|
||||
// Search 获取API列表
|
||||
Search(ctx *gin.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error)
|
||||
Search(ctx *gin.Context, keyword string, serviceId string) ([]*router_dto.Item, error)
|
||||
// Create 创建API
|
||||
Create(ctx *gin.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error)
|
||||
Create(ctx *gin.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error)
|
||||
// Edit 编辑API
|
||||
Edit(ctx *gin.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error)
|
||||
Edit(ctx *gin.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error)
|
||||
// Delete 删除API
|
||||
Delete(ctx *gin.Context, serviceId string, apiId string) error
|
||||
// Prefix 获取API前缀
|
||||
@@ -36,7 +36,7 @@ type IAPIDocController interface {
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IAPIController](func() reflect.Value {
|
||||
autowire.Auto[IRouterController](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlAPIController))
|
||||
})
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/APIParkLab/APIPark/module/api"
|
||||
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
|
||||
"github.com/APIParkLab/APIPark/module/catalogue"
|
||||
"github.com/APIParkLab/APIPark/module/router"
|
||||
"github.com/APIParkLab/APIPark/module/service"
|
||||
"github.com/APIParkLab/APIPark/module/subscribe"
|
||||
"github.com/APIParkLab/APIPark/module/team"
|
||||
@@ -23,7 +23,7 @@ type imlExportConfigController struct {
|
||||
teamModule team.ITeamExportModule `autowired:""`
|
||||
serviceModule service.IExportServiceModule `autowired:""`
|
||||
appModule service.IExportAppModule `autowired:""`
|
||||
apiModule api.IExportApiModule `autowired:""`
|
||||
routerModule router.IExportRouterModule `autowired:""`
|
||||
upstreamModule upstream.IExportUpstreamModule `autowired:""`
|
||||
applicationAuthorizationModule application_authorization.IExportAuthorizationModule `autowired:""`
|
||||
catalogueModule catalogue.IExportCatalogueModule `autowired:""`
|
||||
@@ -114,7 +114,7 @@ func (i *imlExportConfigController) appendFiles(ctx *gin.Context) ([]*ExportFile
|
||||
},
|
||||
{
|
||||
exportFunc: func(ctx *gin.Context) (interface{}, error) {
|
||||
return i.apiModule.ExportAll(ctx)
|
||||
return i.routerModule.ExportAll(ctx)
|
||||
},
|
||||
driver: "api",
|
||||
},
|
||||
|
||||
+10
-14
@@ -6,8 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/APIParkLab/APIPark/module/api"
|
||||
api_dto "github.com/APIParkLab/APIPark/module/api/dto"
|
||||
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
|
||||
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
|
||||
"github.com/APIParkLab/APIPark/module/catalogue"
|
||||
@@ -16,6 +14,8 @@ import (
|
||||
"github.com/APIParkLab/APIPark/module/publish/dto"
|
||||
"github.com/APIParkLab/APIPark/module/release"
|
||||
dto2 "github.com/APIParkLab/APIPark/module/release/dto"
|
||||
"github.com/APIParkLab/APIPark/module/router"
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
"github.com/APIParkLab/APIPark/module/service"
|
||||
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
||||
"github.com/APIParkLab/APIPark/module/subscribe"
|
||||
@@ -52,7 +52,7 @@ type imlImportConfigController struct {
|
||||
teamModule team.ITeamModule `autowired:""`
|
||||
serviceModule service.IServiceModule `autowired:""`
|
||||
appModule service.IAppModule `autowired:""`
|
||||
apiModule api.IApiModule `autowired:""`
|
||||
apiModule router.IRouterModule `autowired:""`
|
||||
upstreamModule upstream.IUpstreamModule `autowired:""`
|
||||
applicationAuthorizationModule application_authorization.IAuthorizationModule `autowired:""`
|
||||
catalogueModule catalogue.ICatalogueModule `autowired:""`
|
||||
@@ -231,14 +231,14 @@ func (i *imlImportConfigController) importApplications(ctx context.Context) erro
|
||||
}
|
||||
|
||||
func (i *imlImportConfigController) importApis(ctx context.Context) error {
|
||||
data, err := unmarshal[api_dto.ExportAPI]("api")
|
||||
data, err := unmarshal[router_dto.Export]("api")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range data {
|
||||
var proxy *api_dto.InputProxy
|
||||
var proxy *router_dto.InputProxy
|
||||
if d.Proxy != nil {
|
||||
proxy = &api_dto.InputProxy{
|
||||
proxy = &router_dto.InputProxy{
|
||||
Path: d.Proxy.Path,
|
||||
Timeout: d.Proxy.Timeout,
|
||||
Retry: d.Proxy.Retry,
|
||||
@@ -253,11 +253,10 @@ func (i *imlImportConfigController) importApis(ctx context.Context) error {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
_, err = i.apiModule.Create(ctx, d.Service, &api_dto.CreateApi{
|
||||
_, err = i.apiModule.Create(ctx, d.Service, &router_dto.Create{
|
||||
Id: d.Id,
|
||||
Name: d.Name,
|
||||
Path: d.Path,
|
||||
Method: d.Method,
|
||||
Methods: d.Method,
|
||||
Description: d.Description,
|
||||
MatchRules: d.MatchRules,
|
||||
Proxy: proxy,
|
||||
@@ -268,11 +267,8 @@ func (i *imlImportConfigController) importApis(ctx context.Context) error {
|
||||
|
||||
continue
|
||||
}
|
||||
info := &api_dto.EditApi{
|
||||
Info: api_dto.EditInfo{
|
||||
Name: &d.Name,
|
||||
Description: &d.Description,
|
||||
},
|
||||
info := &router_dto.Edit{
|
||||
|
||||
Proxy: proxy,
|
||||
//Doc: &d.Doc,
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@ func IndexHtml(ginCtx *gin.Context) {
|
||||
|
||||
func (f *Frontend) Api() []pm3.Api {
|
||||
return []pm3.Api{
|
||||
pm3.CreateApiSimple(http.MethodGet, "/favicon.ico", func(ginCtx *gin.Context) {
|
||||
pm3.CreateRouterSimple(http.MethodGet, "/favicon.ico", func(ginCtx *gin.Context) {
|
||||
ginCtx.Data(http.StatusOK, iconType, iconContent)
|
||||
}),
|
||||
pm3.CreateApiSimple(http.MethodGet, "/vite.svg", func(ginCtx *gin.Context) {
|
||||
pm3.CreateRouterSimple(http.MethodGet, "/vite.svg", func(ginCtx *gin.Context) {
|
||||
ginCtx.Data(http.StatusOK, viteContentType, viteContent)
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
"reflect"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
api_dto "github.com/APIParkLab/APIPark/module/api/dto"
|
||||
)
|
||||
|
||||
type IApiModule interface {
|
||||
// Detail 获取API详情
|
||||
Detail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error)
|
||||
// SimpleDetail 获取API简要详情
|
||||
SimpleDetail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiSimpleDetail, error)
|
||||
// Search 获取API列表
|
||||
Search(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error)
|
||||
// SimpleSearch 获取API简要列表
|
||||
SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiSimpleItem, error)
|
||||
SimpleList(ctx context.Context, serviceId string) ([]*api_dto.ApiSimpleItem, error)
|
||||
// Create 创建API
|
||||
Create(ctx context.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error)
|
||||
// Edit 编辑API
|
||||
Edit(ctx context.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error)
|
||||
// Delete 删除API
|
||||
Delete(ctx context.Context, serviceId string, apiId string) error
|
||||
// Copy 复制API
|
||||
Copy(ctx context.Context, serviceId string, apiId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error)
|
||||
// Prefix 获取API前缀
|
||||
Prefix(ctx context.Context, serviceId string) (string, error)
|
||||
|
||||
//ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, error)
|
||||
}
|
||||
|
||||
type IExportApiModule interface {
|
||||
system.IExportModule[api_dto.ExportAPI]
|
||||
}
|
||||
|
||||
func init() {
|
||||
apiModule := new(imlApiModule)
|
||||
autowire.Auto[IApiModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
|
||||
autowire.Auto[IExportApiModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package api_dto
|
||||
package router_dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
@@ -20,14 +19,15 @@ var validMethods = map[string]struct{}{
|
||||
"OPTIONS": {},
|
||||
}
|
||||
|
||||
type CreateApi struct {
|
||||
type Create struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
Methods []string `json:"methods"`
|
||||
Description string `json:"description"`
|
||||
Protocols []string `json:"protocols"`
|
||||
MatchRules []Match `json:"match"`
|
||||
Proxy *InputProxy `json:"proxy"`
|
||||
Disable bool `json:"disable"`
|
||||
}
|
||||
|
||||
type InputProxy struct {
|
||||
@@ -45,46 +45,28 @@ type Match struct {
|
||||
Pattern string `json:"pattern"`
|
||||
}
|
||||
|
||||
func (a *CreateApi) Validate() error {
|
||||
func (a *Create) Validate() error {
|
||||
if a.Id == "" {
|
||||
return errors.New("id is null")
|
||||
}
|
||||
if a.Name == "" {
|
||||
return errors.New("name is null")
|
||||
}
|
||||
a.Path = fmt.Sprintf("/%s", strings.TrimPrefix(a.Path, "/"))
|
||||
a.Method = strings.ToUpper(a.Method)
|
||||
if _, ok := validMethods[a.Method]; !ok {
|
||||
return fmt.Errorf("method(%s) is invalid", a.Method)
|
||||
for _, method := range a.Methods {
|
||||
if _, ok := validMethods[method]; !ok {
|
||||
return fmt.Errorf("method(%s) is invalid", method)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *CreateApi) ToServiceRouter() *api.Router {
|
||||
router := &api.Router{
|
||||
Method: a.Method,
|
||||
Path: a.Path,
|
||||
}
|
||||
for _, match := range a.MatchRules {
|
||||
router.MatchRules = append(router.MatchRules, &api.Match{
|
||||
Position: match.Position,
|
||||
MatchType: match.MatchType,
|
||||
Key: match.Key,
|
||||
Pattern: match.Pattern,
|
||||
})
|
||||
}
|
||||
return router
|
||||
}
|
||||
|
||||
type EditApi struct {
|
||||
Info EditInfo `json:"info"`
|
||||
Proxy *InputProxy `json:"proxy"`
|
||||
//Doc *map[string]interface{} `json:"doc"`
|
||||
}
|
||||
|
||||
type EditInfo struct {
|
||||
Name *string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
type Edit struct {
|
||||
Description *string `json:"description"`
|
||||
Proxy *InputProxy `json:"proxy"`
|
||||
Path *string `json:"path"`
|
||||
Methods *[]string `json:"methods"`
|
||||
Protocols *[]string `json:"protocols"`
|
||||
MatchRules *[]Match `json:"match"`
|
||||
Disable *bool `json:"disable"`
|
||||
}
|
||||
|
||||
func ToServiceProxy(proxy *InputProxy) *api.Proxy {
|
||||
@@ -100,8 +82,7 @@ func ToServiceProxy(proxy *InputProxy) *api.Proxy {
|
||||
})
|
||||
|
||||
return &api.Proxy{
|
||||
Path: proxy.Path,
|
||||
//Upstream: proxy.Upstream,
|
||||
Path: proxy.Path,
|
||||
Timeout: proxy.Timeout,
|
||||
Retry: proxy.Retry,
|
||||
Extends: proxy.Extends,
|
||||
@@ -110,19 +91,6 @@ func ToServiceProxy(proxy *InputProxy) *api.Proxy {
|
||||
}
|
||||
}
|
||||
|
||||
func ToServiceDocument(doc map[string]interface{}) *api.Document {
|
||||
if doc == nil {
|
||||
return &api.Document{
|
||||
Content: "{}",
|
||||
}
|
||||
}
|
||||
content, _ := json.Marshal(doc)
|
||||
|
||||
return &api.Document{
|
||||
Content: string(content),
|
||||
}
|
||||
}
|
||||
|
||||
type ListInput struct {
|
||||
Projects []string `json:"projects"`
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package api_dto
|
||||
package router_dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/eolinker/go-common/auto"
|
||||
)
|
||||
|
||||
type ApiItem struct {
|
||||
type Item struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Methods []string `json:"methods"`
|
||||
@@ -22,27 +22,27 @@ type ApiItem struct {
|
||||
CanDelete bool `json:"can_delete"`
|
||||
}
|
||||
|
||||
type ApiSimpleItem struct {
|
||||
type SimpleItem struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"request_path"`
|
||||
}
|
||||
|
||||
type ApiDetail struct {
|
||||
ApiSimpleDetail
|
||||
type Detail struct {
|
||||
SimpleDetail
|
||||
Proxy *Proxy `json:"proxy"`
|
||||
//Doc map[string]interface{} `json:"doc"`
|
||||
}
|
||||
|
||||
func GenApiSimpleDetail(api *api.Info) *ApiSimpleDetail {
|
||||
func GenSimpleDetail(api *api.Info) *SimpleDetail {
|
||||
match := make([]Match, 0)
|
||||
if api.Match == "" {
|
||||
api.Match = "[]"
|
||||
}
|
||||
json.Unmarshal([]byte(api.Match), &match)
|
||||
|
||||
return &ApiSimpleDetail{
|
||||
return &SimpleDetail{
|
||||
Id: api.UUID,
|
||||
Name: api.Name,
|
||||
Description: api.Description,
|
||||
@@ -56,7 +56,7 @@ func GenApiSimpleDetail(api *api.Info) *ApiSimpleDetail {
|
||||
}
|
||||
}
|
||||
|
||||
type ApiSimpleDetail struct {
|
||||
type SimpleDetail struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
@@ -106,11 +106,11 @@ type Header struct {
|
||||
Opt string `json:"opt"`
|
||||
}
|
||||
|
||||
type ExportAPI struct {
|
||||
type Export struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Method string `json:"method"`
|
||||
Method []string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
MatchRules []Match `json:"match"`
|
||||
Service string `json:"service"`
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
|
||||
api_dto "github.com/APIParkLab/APIPark/module/api/dto"
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
)
|
||||
|
||||
var (
|
||||
_ IApiModule = (*imlApiModule)(nil)
|
||||
_ IExportApiModule = (*imlApiModule)(nil)
|
||||
_ IRouterModule = (*imlRouterModule)(nil)
|
||||
_ IExportRouterModule = (*imlRouterModule)(nil)
|
||||
)
|
||||
var (
|
||||
asServer = map[string]bool{
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type imlApiModule struct {
|
||||
type imlRouterModule struct {
|
||||
teamService team.ITeamService `autowired:""`
|
||||
serviceService service.IServiceService `autowired:""`
|
||||
apiService api.IAPIService `autowired:""`
|
||||
@@ -45,7 +45,7 @@ type imlApiModule struct {
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, error) {
|
||||
func (i *imlRouterModule) ExportAll(ctx context.Context) ([]*router_dto.Export, error) {
|
||||
|
||||
apiList, err := i.apiService.ListInfo(ctx)
|
||||
if err != nil {
|
||||
@@ -62,13 +62,13 @@ func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, err
|
||||
return c.Target
|
||||
})
|
||||
|
||||
return utils.SliceToSlice(apiList, func(a *api.Info) *api_dto.ExportAPI {
|
||||
match := make([]api_dto.Match, 0)
|
||||
return utils.SliceToSlice(apiList, func(a *api.Info) *router_dto.Export {
|
||||
match := make([]router_dto.Match, 0)
|
||||
if a.Match == "" {
|
||||
a.Match = "[]"
|
||||
}
|
||||
json.Unmarshal([]byte(a.Match), &match)
|
||||
info := &api_dto.ExportAPI{
|
||||
info := &router_dto.Export{
|
||||
Id: a.UUID,
|
||||
Name: a.Name,
|
||||
Description: a.Description,
|
||||
@@ -78,14 +78,14 @@ func (i *imlApiModule) ExportAll(ctx context.Context) ([]*api_dto.ExportAPI, err
|
||||
Team: a.Team,
|
||||
}
|
||||
if v, ok := proxyCommitMap[a.UUID]; ok {
|
||||
info.Proxy = api_dto.FromServiceProxy(v.Data)
|
||||
info.Proxy = router_dto.FromServiceProxy(v.Data)
|
||||
}
|
||||
|
||||
return info
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api_dto.ApiSimpleItem, error) {
|
||||
func (i *imlRouterModule) SimpleList(ctx context.Context, serviceId string) ([]*router_dto.SimpleItem, error) {
|
||||
|
||||
list, err := i.apiService.ListForService(ctx, serviceId)
|
||||
apiInfos, err := i.apiService.ListInfo(ctx, utils.SliceToSlice(list, func(s *api.API) string {
|
||||
@@ -95,8 +95,8 @@ func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiSimpleItem {
|
||||
return &api_dto.ApiSimpleItem{
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.SimpleItem {
|
||||
return &router_dto.SimpleItem{
|
||||
Id: item.UUID,
|
||||
Name: item.Name,
|
||||
Path: item.Path,
|
||||
@@ -105,7 +105,7 @@ func (i *imlApiModule) SimpleList(ctx context.Context, serviceId string) ([]*api
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiDetail, error) {
|
||||
func (i *imlRouterModule) Detail(ctx context.Context, serviceId string, apiId string) (*router_dto.Detail, error) {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -116,8 +116,8 @@ func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId strin
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiDetail := &api_dto.ApiDetail{
|
||||
ApiSimpleDetail: *api_dto.GenApiSimpleDetail(detail),
|
||||
apiDetail := &router_dto.Detail{
|
||||
SimpleDetail: *router_dto.GenSimpleDetail(detail),
|
||||
}
|
||||
proxy, err := i.apiService.LatestProxy(ctx, apiId)
|
||||
if err != nil {
|
||||
@@ -126,13 +126,13 @@ func (i *imlApiModule) Detail(ctx context.Context, serviceId string, apiId strin
|
||||
}
|
||||
}
|
||||
if proxy != nil {
|
||||
apiDetail.Proxy = api_dto.FromServiceProxy(proxy.Data)
|
||||
apiDetail.Proxy = router_dto.FromServiceProxy(proxy.Data)
|
||||
}
|
||||
|
||||
return apiDetail, nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) SimpleDetail(ctx context.Context, serviceId string, apiId string) (*api_dto.ApiSimpleDetail, error) {
|
||||
func (i *imlRouterModule) SimpleDetail(ctx context.Context, serviceId string, apiId string) (*router_dto.SimpleDetail, error) {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -143,10 +143,10 @@ func (i *imlApiModule) SimpleDetail(ctx context.Context, serviceId string, apiId
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return api_dto.GenApiSimpleDetail(detail), nil
|
||||
return router_dto.GenSimpleDetail(detail), nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiItem, error) {
|
||||
func (i *imlRouterModule) Search(ctx context.Context, keyword string, serviceId string) ([]*router_dto.Item, error) {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -167,8 +167,8 @@ func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId str
|
||||
utils.Sort(apiInfos, func(a, b *api.Info) bool {
|
||||
return a.UpdateAt.After(b.UpdateAt)
|
||||
})
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiItem {
|
||||
return &api_dto.ApiItem{
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.Item {
|
||||
return &router_dto.Item{
|
||||
Id: item.UUID,
|
||||
Name: item.Name,
|
||||
Methods: item.Methods,
|
||||
@@ -185,7 +185,7 @@ func (i *imlApiModule) Search(ctx context.Context, keyword string, serviceId str
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*api_dto.ApiSimpleItem, error) {
|
||||
func (i *imlRouterModule) SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*router_dto.SimpleItem, error) {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -203,8 +203,8 @@ func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, service
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *api_dto.ApiSimpleItem {
|
||||
return &api_dto.ApiSimpleItem{
|
||||
out := utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.SimpleItem {
|
||||
return &router_dto.SimpleItem{
|
||||
Id: item.UUID,
|
||||
Name: item.Name,
|
||||
//Methods: item.Methods,
|
||||
@@ -214,7 +214,7 @@ func (i *imlApiModule) SimpleSearch(ctx context.Context, keyword string, service
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) {
|
||||
func (i *imlRouterModule) Create(ctx context.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) {
|
||||
info, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -233,24 +233,25 @@ func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dt
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s%s", prefix, dto.Path)
|
||||
err = i.apiService.Exist(ctx, "", &api.ExistAPI{Path: dto.Path, Method: dto.Method})
|
||||
|
||||
err = i.apiService.Exist(ctx, "", &api.Exist{Path: dto.Path, Methods: dto.Methods})
|
||||
if err != nil {
|
||||
return fmt.Errorf("api path %s,method: %s already exist", dto.Path, dto.Method)
|
||||
return err
|
||||
}
|
||||
proxy := api_dto.ToServiceProxy(dto.Proxy)
|
||||
|
||||
proxy := router_dto.ToServiceProxy(dto.Proxy)
|
||||
err = i.apiService.SaveProxy(ctx, dto.Id, proxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
match, _ := json.Marshal(dto.MatchRules)
|
||||
return i.apiService.Create(ctx, &api.CreateAPI{
|
||||
return i.apiService.Create(ctx, &api.Create{
|
||||
UUID: dto.Id,
|
||||
Name: dto.Name,
|
||||
Description: dto.Description,
|
||||
Service: serviceId,
|
||||
Team: info.Team,
|
||||
Method: dto.Method,
|
||||
Methods: dto.Methods,
|
||||
Path: path,
|
||||
Match: string(match),
|
||||
})
|
||||
@@ -261,24 +262,32 @@ func (i *imlApiModule) Create(ctx context.Context, serviceId string, dto *api_dt
|
||||
return i.SimpleDetail(ctx, serviceId, dto.Id)
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Edit(ctx context.Context, serviceId string, apiId string, dto *api_dto.EditApi) (*api_dto.ApiSimpleDetail, error) {
|
||||
func (i *imlRouterModule) Edit(ctx context.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error) {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
|
||||
var up *string
|
||||
if dto.Proxy != nil {
|
||||
err = i.apiService.SaveProxy(ctx, apiId, api_dto.ToServiceProxy(dto.Proxy))
|
||||
err = i.apiService.SaveProxy(ctx, apiId, router_dto.ToServiceProxy(dto.Proxy))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = i.apiService.Save(ctx, apiId, &api.EditAPI{
|
||||
Name: dto.Info.Name,
|
||||
Description: dto.Info.Description,
|
||||
Upstream: up,
|
||||
var match *string
|
||||
if dto.MatchRules != nil {
|
||||
ml, _ := json.Marshal(dto.MatchRules)
|
||||
m := string(ml)
|
||||
match = &m
|
||||
}
|
||||
err = i.apiService.Save(ctx, apiId, &api.Edit{
|
||||
Description: dto.Description,
|
||||
Methods: dto.Methods,
|
||||
Protocols: dto.Protocols,
|
||||
Disable: dto.Disable,
|
||||
Path: dto.Path,
|
||||
Match: match,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -293,7 +302,7 @@ func (i *imlApiModule) Edit(ctx context.Context, serviceId string, apiId string,
|
||||
return i.SimpleDetail(ctx, serviceId, apiId)
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Delete(ctx context.Context, serviceId string, apiId string) error {
|
||||
func (i *imlRouterModule) Delete(ctx context.Context, serviceId string, apiId string) error {
|
||||
_, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -301,67 +310,67 @@ func (i *imlApiModule) Delete(ctx context.Context, serviceId string, apiId strin
|
||||
return i.apiService.Delete(ctx, apiId)
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Copy(ctx context.Context, serviceId string, apiId string, dto *api_dto.CreateApi) (*api_dto.ApiSimpleDetail, error) {
|
||||
info, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldApi, err := i.apiService.Get(ctx, apiId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefix, err := i.Prefix(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
|
||||
if dto.Id == "" {
|
||||
dto.Id = uuid.New().String()
|
||||
}
|
||||
err = dto.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//func (i *imlRouterModule) Copy(ctx context.Context, serviceId string, apiId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error) {
|
||||
// info, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// oldApi, err := i.apiService.Get(ctx, apiId)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// prefix, err := i.Prefix(ctx, serviceId)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
|
||||
// if dto.Id == "" {
|
||||
// dto.Id = uuid.New().String()
|
||||
// }
|
||||
// err = dto.Validate()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// path := fmt.Sprintf("%s/%s", strings.TrimSuffix(prefix, "/"), strings.TrimPrefix(dto.Path, "/"))
|
||||
// err = i.apiService.Exist(ctx, serviceId, &api.Exist{Path: path, Methods: dto.Methods})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// proxy, err := i.apiService.LatestProxy(ctx, oldApi.UUID)
|
||||
// if err != nil {
|
||||
// if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// //upstreamId := ""
|
||||
// if proxy != nil {
|
||||
// err = i.apiService.SaveProxy(ctx, dto.Id, proxy.Data)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// match, _ := json.Marshal(dto.MatchRules)
|
||||
// return i.apiService.Create(ctx, &api.Create{
|
||||
// UUID: dto.Id,
|
||||
// Name: dto.Name,
|
||||
// Service: serviceId,
|
||||
// Team: info.Team,
|
||||
// Methods: dto.Methods,
|
||||
// Path: path,
|
||||
// Match: string(match),
|
||||
// })
|
||||
//
|
||||
// })
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return i.SimpleDetail(ctx, serviceId, dto.Id)
|
||||
//}
|
||||
|
||||
path := fmt.Sprintf("%s/%s", strings.TrimSuffix(prefix, "/"), strings.TrimPrefix(dto.Path, "/"))
|
||||
err = i.apiService.Exist(ctx, serviceId, &api.ExistAPI{Path: path, Method: dto.Method})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proxy, err := i.apiService.LatestProxy(ctx, oldApi.UUID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
//upstreamId := ""
|
||||
if proxy != nil {
|
||||
err = i.apiService.SaveProxy(ctx, dto.Id, proxy.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
match, _ := json.Marshal(dto.MatchRules)
|
||||
return i.apiService.Create(ctx, &api.CreateAPI{
|
||||
UUID: dto.Id,
|
||||
Name: dto.Name,
|
||||
Service: serviceId,
|
||||
Team: info.Team,
|
||||
Method: dto.Method,
|
||||
Path: path,
|
||||
Match: string(match),
|
||||
})
|
||||
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i.SimpleDetail(ctx, serviceId, dto.Id)
|
||||
}
|
||||
|
||||
func (i *imlApiModule) Prefix(ctx context.Context, serviceId string) (string, error) {
|
||||
func (i *imlRouterModule) Prefix(ctx context.Context, serviceId string) (string, error) {
|
||||
pInfo, err := i.serviceService.Check(ctx, serviceId, asServer)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -0,0 +1,48 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
"reflect"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
)
|
||||
|
||||
type IRouterModule interface {
|
||||
// Detail 获取API详情
|
||||
Detail(ctx context.Context, serviceId string, apiId string) (*router_dto.Detail, error)
|
||||
// SimpleDetail 获取API简要详情
|
||||
SimpleDetail(ctx context.Context, serviceId string, apiId string) (*router_dto.SimpleDetail, error)
|
||||
// Search 获取API列表
|
||||
Search(ctx context.Context, keyword string, serviceId string) ([]*router_dto.Item, error)
|
||||
// SimpleSearch 获取API简要列表
|
||||
SimpleSearch(ctx context.Context, keyword string, serviceId string) ([]*router_dto.SimpleItem, error)
|
||||
SimpleList(ctx context.Context, serviceId string) ([]*router_dto.SimpleItem, error)
|
||||
// Create 创建API
|
||||
Create(ctx context.Context, serviceId string, dto *router_dto.Create) (*router_dto.SimpleDetail, error)
|
||||
// Edit 编辑API
|
||||
Edit(ctx context.Context, serviceId string, apiId string, dto *router_dto.Edit) (*router_dto.SimpleDetail, error)
|
||||
// Delete 删除API
|
||||
Delete(ctx context.Context, serviceId string, apiId string) error
|
||||
// Prefix 获取API前缀
|
||||
Prefix(ctx context.Context, serviceId string) (string, error)
|
||||
|
||||
//ExportAll(ctx context.Context) ([]*router_dto.Export, error)
|
||||
}
|
||||
|
||||
type IExportRouterModule interface {
|
||||
system.IExportModule[router_dto.Export]
|
||||
}
|
||||
|
||||
func init() {
|
||||
apiModule := new(imlRouterModule)
|
||||
autowire.Auto[IRouterModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
|
||||
autowire.Auto[IExportRouterModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
}
|
||||
+6
-6
@@ -8,12 +8,12 @@ import (
|
||||
|
||||
func (p *plugin) apiApis() []pm3.Api {
|
||||
return []pm3.Api{
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/apis", []string{"context", "query:keyword", "query:service"}, []string{"apis"}, p.apiController.Search),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api/detail", []string{"context", "query:service", "query:api"}, []string{"api"}, p.apiController.Detail),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/service/api", []string{"context", "query:service", "body"}, []string{"api"}, p.apiController.Create),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/api", []string{"context", "query:service", "query:api", "body"}, []string{"api"}, p.apiController.Edit),
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/service/api", []string{"context", "query:service", "query:api"}, nil, p.apiController.Delete),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api/define", []string{"context", "query:service"}, []string{"prefix", "force"}, p.apiController.Prefix),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/routers", []string{"context", "query:keyword", "query:service"}, []string{"routers"}, p.routerController.Search),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/router/detail", []string{"context", "query:service", "query:router"}, []string{"router"}, p.routerController.Detail),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/service/router", []string{"context", "query:service", "body"}, []string{"router"}, p.routerController.Create),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/router", []string{"context", "query:service", "query:router", "body"}, []string{"router"}, p.routerController.Edit),
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/service/router", []string{"context", "query:service", "query:router"}, nil, p.routerController.Delete),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/router/define", []string{"context", "query:service"}, []string{"prefix", "force"}, p.routerController.Prefix),
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/api_doc", []string{"context", "query:service", "body"}, []string{"doc"}, p.apiDocController.UpdateDoc),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/api_doc", []string{"context", "query:service"}, []string{"doc"}, p.apiDocController.GetDoc),
|
||||
|
||||
@@ -2,6 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"github.com/APIParkLab/APIPark/controller/monitor"
|
||||
"github.com/APIParkLab/APIPark/controller/router"
|
||||
"github.com/APIParkLab/APIPark/controller/system"
|
||||
"net/http"
|
||||
|
||||
@@ -21,8 +22,6 @@ import (
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/subscribe"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/api"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/upstream"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/service"
|
||||
@@ -66,8 +65,8 @@ type plugin struct {
|
||||
monitorConfigController monitor.IMonitorConfigController `autowired:""`
|
||||
catalogueController catalogue.ICatalogueController `autowired:""`
|
||||
upstreamController upstream.IUpstreamController `autowired:""`
|
||||
apiController api.IAPIController `autowired:""`
|
||||
apiDocController api.IAPIDocController `autowired:""`
|
||||
routerController router.IRouterController `autowired:""`
|
||||
apiDocController router.IAPIDocController `autowired:""`
|
||||
subscribeController subscribe.ISubscribeController `autowired:""`
|
||||
appAuthorizationController application_authorization.IAuthorizationController `autowired:""`
|
||||
releaseController release.IReleaseController `autowired:""`
|
||||
|
||||
@@ -2,7 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
|
||||
"github.com/eolinker/go-common/pm3"
|
||||
)
|
||||
|
||||
|
||||
@@ -235,28 +235,42 @@ team:
|
||||
cname: 服务
|
||||
value: 'service'
|
||||
children:
|
||||
- name: api
|
||||
cname: API
|
||||
value: 'api'
|
||||
- name: router
|
||||
cname: 路由
|
||||
value: 'router'
|
||||
children:
|
||||
- name: view
|
||||
cname: 查看
|
||||
value: 'view'
|
||||
guest_allow: true
|
||||
apis:
|
||||
- "GET:/api/v1/service/apis"
|
||||
- "GET:/api/v1/service/api/detail"
|
||||
- "GET:/api/v1/service/api/detail/simple"
|
||||
- "GET:/api/v1/service/api/define"
|
||||
- "GET:/api/v1/service/apis/simple"
|
||||
- "GET:/api/v1/service/routers"
|
||||
- "GET:/api/v1/service/router/detail"
|
||||
- "GET:/api/v1/service/router/detail/simple"
|
||||
- "GET:/api/v1/service/router/define"
|
||||
- name: manager
|
||||
cname: 管理
|
||||
value: 'manager'
|
||||
apis:
|
||||
- "POST:/api/v1/service/api"
|
||||
- "PUT:/api/v1/service/api"
|
||||
- "DELETE:/api/v1/service/api"
|
||||
- "POST:/api/v1/service/api/copy"
|
||||
- "POST:/api/v1/service/router"
|
||||
- "PUT:/api/v1/service/router"
|
||||
- "DELETE:/api/v1/service/router"
|
||||
- name: api_doc
|
||||
cname: API文档
|
||||
value: 'api_doc'
|
||||
children:
|
||||
- name: view
|
||||
cname: 查看
|
||||
value: 'view'
|
||||
guest_allow: true
|
||||
apis:
|
||||
- "GET:/api/v1/service/api_doc"
|
||||
- name: manager
|
||||
cname: 管理
|
||||
value: 'manager'
|
||||
apis:
|
||||
- "PUT:/api/v1/service/api_doc"
|
||||
- "POST:/api/v1/service/api_doc/upload"
|
||||
- name: upstream
|
||||
cname: 上游
|
||||
value: 'upstream'
|
||||
|
||||
@@ -83,8 +83,10 @@ team:
|
||||
- team.application.authorization.view
|
||||
- team.application.subscription.manager
|
||||
- team.application.subscription.view
|
||||
- team.service.api.manager
|
||||
- team.service.api.view
|
||||
- team.service.api_doc.view
|
||||
- team.service.api_doc.manager
|
||||
- team.service.router.manager
|
||||
- team.service.router.view
|
||||
- team.service.release.manager
|
||||
- team.service.release.view
|
||||
- team.service.service.manager
|
||||
@@ -103,8 +105,10 @@ team:
|
||||
- team.service.service.manager
|
||||
- team.service.upstream.manager
|
||||
- team.service.upstream.view
|
||||
- team.service.api.manager
|
||||
- team.service.api.view
|
||||
- team.service.api_doc.view
|
||||
- team.service.api_doc.manager
|
||||
- team.service.router.manager
|
||||
- team.service.router.view
|
||||
- team.service.subscription.manager
|
||||
- team.service.subscription.view
|
||||
- team.service.release.manager
|
||||
@@ -115,8 +119,10 @@ team:
|
||||
permits:
|
||||
- team.service.upstream.manager
|
||||
- team.service.upstream.view
|
||||
- team.service.api.manager
|
||||
- team.service.api.view
|
||||
- team.service.api_doc.view
|
||||
- team.service.api_doc.manager
|
||||
- team.service.router.manager
|
||||
- team.service.router.view
|
||||
- team.service.release.manager
|
||||
- team.service.release.view
|
||||
- team.team.member.view
|
||||
@@ -142,7 +148,7 @@ team:
|
||||
permits:
|
||||
- team.application.authorization.view
|
||||
- team.application.subscription.view
|
||||
- team.service.api.view
|
||||
- team.service.router.view
|
||||
- team.service.release.view
|
||||
- team.service.subscription.view
|
||||
- team.service.upstream.view
|
||||
|
||||
@@ -20,10 +20,14 @@ type imlAPIDocService struct {
|
||||
}
|
||||
|
||||
func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, input *UpdateDoc) error {
|
||||
// 校验内容格式是否正确
|
||||
if err := ValidDoc(input.Content); err != nil {
|
||||
doc, err := NewDocLoader(input.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := doc.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := i.store.First(ctx, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
})
|
||||
@@ -38,10 +42,12 @@ func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, inpu
|
||||
Content: input.Content,
|
||||
Updater: operator,
|
||||
UpdateAt: time.Now(),
|
||||
APICount: doc.APICount(),
|
||||
})
|
||||
}
|
||||
info.Updater = operator
|
||||
info.UpdateAt = time.Now()
|
||||
info.APICount = doc.APICount()
|
||||
return i.store.Save(ctx, info)
|
||||
}
|
||||
|
||||
|
||||
+20
-17
@@ -30,29 +30,32 @@ var (
|
||||
loader = openapi3.NewLoader()
|
||||
)
|
||||
|
||||
func ValidDoc(content string) error {
|
||||
doc, err := loader.LoadFromData([]byte(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load OpenAPI document: %v", err)
|
||||
}
|
||||
err = doc.Validate(loader.Context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenAPI document is not valid: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
type DocLoader struct {
|
||||
doc *openapi3.T
|
||||
}
|
||||
|
||||
func DocAPICount(content string) (int64, error) {
|
||||
func NewDocLoader(content string) (*DocLoader, error) {
|
||||
doc, err := loader.LoadFromData([]byte(content))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return nil, fmt.Errorf("load doc error:%v", err)
|
||||
}
|
||||
if doc.Paths == nil {
|
||||
return 0, nil
|
||||
return &DocLoader{doc: doc}, nil
|
||||
}
|
||||
|
||||
func (d *DocLoader) Valid() error {
|
||||
if d.doc == nil {
|
||||
return fmt.Errorf("doc is nil")
|
||||
}
|
||||
|
||||
return d.doc.Validate(loader.Context)
|
||||
}
|
||||
|
||||
func (d *DocLoader) APICount() int64 {
|
||||
if d.doc == nil || d.doc.Paths == nil {
|
||||
return 0
|
||||
}
|
||||
var count int64
|
||||
for _, item := range doc.Paths.Map() {
|
||||
for _, item := range d.doc.Paths.Map() {
|
||||
if item.Get != nil {
|
||||
count++
|
||||
}
|
||||
@@ -78,5 +81,5 @@ func DocAPICount(content string) (int64, error) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count, nil
|
||||
return count
|
||||
}
|
||||
|
||||
+54
-48
@@ -50,7 +50,7 @@ func (i *imlAPIService) ListInfoForService(ctx context.Context, serviceId string
|
||||
apis, err := i.store.List(ctx, map[string]interface{}{
|
||||
"service": serviceId,
|
||||
})
|
||||
aids := utils.SliceToSlice(apis, func(a *api.Api) int64 {
|
||||
aids := utils.SliceToSlice(apis, func(a *api.API) int64 {
|
||||
return a.Id
|
||||
})
|
||||
list, err := i.apiInfoStore.List(ctx, map[string]interface{}{
|
||||
@@ -84,7 +84,7 @@ func (i *imlAPIService) GetInfo(ctx context.Context, aid string) (*Info, error)
|
||||
return FromEntityInfo(info), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) error {
|
||||
func (i *imlAPIService) Save(ctx context.Context, id string, model *Edit) error {
|
||||
if model == nil {
|
||||
return errors.New("input is nil")
|
||||
}
|
||||
@@ -93,12 +93,26 @@ func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if model.Name != nil {
|
||||
ev.Name = *model.Name
|
||||
}
|
||||
|
||||
if model.Description != nil {
|
||||
ev.Description = *model.Description
|
||||
}
|
||||
if model.Protocols != nil {
|
||||
ev.Protocol = *model.Protocols
|
||||
}
|
||||
if model.Path != nil {
|
||||
ev.Path = *model.Path
|
||||
}
|
||||
if model.Match != nil {
|
||||
ev.Match = *model.Match
|
||||
}
|
||||
if model.Methods != nil {
|
||||
ev.Method = *model.Methods
|
||||
}
|
||||
if model.Disable != nil {
|
||||
ev.Disable = *model.Disable
|
||||
}
|
||||
|
||||
e := i.apiInfoStore.Save(ctx, ev)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -109,48 +123,31 @@ func (i *imlAPIService) Save(ctx context.Context, id string, model *EditAPI) err
|
||||
}
|
||||
func getLabels(input *api.Info, appends ...string) []string {
|
||||
labels := make([]string, 0, len(appends)+9)
|
||||
labels = append(labels, input.UUID, input.Name, input.Description, input.Method, input.Path, input.Service, input.Team, input.Updater)
|
||||
labels = append(labels, input.UUID, input.Name, input.Description, input.Path, input.Service, input.Team, input.Updater)
|
||||
labels = append(labels, appends...)
|
||||
return labels
|
||||
}
|
||||
func (i *imlAPIService) Create(ctx context.Context, input *CreateAPI) (err error) {
|
||||
func (i *imlAPIService) Create(ctx context.Context, input *Create) (err error) {
|
||||
operater := utils.UserId(ctx)
|
||||
return i.store.Transaction(ctx, func(ctx context.Context) error {
|
||||
t, err := i.store.First(ctx, map[string]interface{}{
|
||||
"method": input.Method,
|
||||
"path": input.Path,
|
||||
})
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if t != nil {
|
||||
return fmt.Errorf("method(%s),path(%s) is exist", input.Method, input.Path)
|
||||
}
|
||||
if input.UUID != "" {
|
||||
a, err := i.store.GetByUUID(ctx, input.UUID)
|
||||
_, err = i.store.GetByUUID(ctx, input.UUID)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
if a != nil {
|
||||
return fmt.Errorf("api(%s) is exist", input.UUID)
|
||||
}
|
||||
|
||||
} else {
|
||||
input.UUID = uuid.NewString()
|
||||
}
|
||||
|
||||
ne := api.Api{
|
||||
Id: 0,
|
||||
ne := api.API{
|
||||
UUID: input.UUID,
|
||||
Name: input.UUID,
|
||||
Service: input.Service,
|
||||
Team: input.Team,
|
||||
Creator: operater,
|
||||
CreateAt: time.Now(),
|
||||
IsDelete: 0,
|
||||
Method: input.Method,
|
||||
Method: input.Methods,
|
||||
Path: input.Path,
|
||||
}
|
||||
err = i.store.Insert(ctx, &ne)
|
||||
@@ -160,18 +157,17 @@ func (i *imlAPIService) Create(ctx context.Context, input *CreateAPI) (err error
|
||||
ev := &api.Info{
|
||||
Id: ne.Id,
|
||||
UUID: ne.UUID,
|
||||
Name: input.Name,
|
||||
Name: ne.UUID,
|
||||
Description: input.Description,
|
||||
Updater: operater,
|
||||
UpdateAt: time.Now(),
|
||||
Creator: operater,
|
||||
CreateAt: time.Now(),
|
||||
//Upstream: input.Upstream,
|
||||
Method: input.Method,
|
||||
Path: input.Path,
|
||||
Match: input.Match,
|
||||
Service: input.Service,
|
||||
Team: input.Team,
|
||||
Method: input.Methods,
|
||||
Path: input.Path,
|
||||
Match: input.Match,
|
||||
Service: input.Service,
|
||||
Team: input.Team,
|
||||
}
|
||||
err = i.apiInfoStore.Save(ctx, ev)
|
||||
if err != nil {
|
||||
@@ -195,19 +191,29 @@ func (i *imlAPIService) CountByService(ctx context.Context, service string) (int
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAPIService) Exist(ctx context.Context, aid string, a *ExistAPI) error {
|
||||
t, err := i.store.First(ctx, map[string]interface{}{
|
||||
"method": a.Method,
|
||||
"path": a.Path,
|
||||
func (i *imlAPIService) Exist(ctx context.Context, aid string, a *Exist) error {
|
||||
list, err := i.store.Search(ctx, "", map[string]interface{}{
|
||||
"path": a.Path,
|
||||
})
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
if t.UUID != aid {
|
||||
return fmt.Errorf("method(%s),path(%s) is exist", a.Method, a.Path)
|
||||
existMethodMap := make(map[string]struct{})
|
||||
for _, t := range list {
|
||||
if len(t.Method) == 0 {
|
||||
if t.UUID != aid {
|
||||
return fmt.Errorf("method(%v),path(%s) is exist", a.Methods, a.Path)
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, m := range t.Method {
|
||||
existMethodMap[m] = struct{}{}
|
||||
}
|
||||
}
|
||||
for _, m := range a.Methods {
|
||||
if _, ok := existMethodMap[m]; ok {
|
||||
return fmt.Errorf("method(%s),path(%s) is exist", m, a.Path)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -219,7 +225,7 @@ func (i *imlAPIService) ListForService(ctx context.Context, serviceId string) ([
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
func (i *imlAPIService) listForService(ctx context.Context, serviceId string, isDelete bool) ([]*api.Api, error) {
|
||||
func (i *imlAPIService) listForService(ctx context.Context, serviceId string, isDelete bool) ([]*api.API, error) {
|
||||
return i.store.ListQuery(ctx, "service=? and is_delete=?", []interface{}{serviceId, isDelete}, "id")
|
||||
}
|
||||
func (i *imlAPIService) ListLatestCommitProxy(ctx context.Context, apiUUID ...string) ([]*commit.Commit[Proxy], error) {
|
||||
@@ -256,9 +262,9 @@ func (i *imlAPIService) GetLabels(ctx context.Context, ids ...string) map[string
|
||||
}
|
||||
|
||||
func (i *imlAPIService) OnComplete() {
|
||||
i.IServiceGet = universally.NewGetSoftDelete[API, api.Api](i.store, FromEntity)
|
||||
i.IServiceGet = universally.NewGetSoftDelete[API, api.API](i.store, FromEntity)
|
||||
|
||||
i.IServiceDelete = universally.NewSoftDelete[api.Api](i.store)
|
||||
i.IServiceDelete = universally.NewSoftDelete[api.API](i.store)
|
||||
|
||||
auto.RegisterService("api", i)
|
||||
}
|
||||
|
||||
+17
-35
@@ -1,9 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/model/plugin_model"
|
||||
@@ -40,17 +37,8 @@ type Info struct {
|
||||
Disable bool
|
||||
}
|
||||
|
||||
func FromEntity(e *api.Api) *API {
|
||||
methods := make([]string, 0)
|
||||
if e.Method != "" {
|
||||
err := json.Unmarshal([]byte(e.Method), &methods)
|
||||
if err != nil {
|
||||
m := strings.ToUpper(e.Method)
|
||||
if m == http.MethodGet || m == http.MethodPost || m == http.MethodPut || m == http.MethodDelete || m == http.MethodPatch || m == http.MethodHead || m == http.MethodOptions {
|
||||
methods = append(methods, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
func FromEntity(e *api.API) *API {
|
||||
|
||||
return &API{
|
||||
UUID: e.UUID,
|
||||
CreateAt: e.CreateAt,
|
||||
@@ -58,23 +46,13 @@ func FromEntity(e *api.Api) *API {
|
||||
Service: e.Service,
|
||||
Team: e.Team,
|
||||
Creator: e.Creator,
|
||||
Method: methods,
|
||||
Method: e.Method,
|
||||
Path: e.Path,
|
||||
Protocols: e.Protocol,
|
||||
}
|
||||
}
|
||||
|
||||
func FromEntityInfo(e *api.Info) *Info {
|
||||
methods := make([]string, 0)
|
||||
if e.Method != "" {
|
||||
err := json.Unmarshal([]byte(e.Method), &methods)
|
||||
if err != nil {
|
||||
m := strings.ToUpper(e.Method)
|
||||
if m == http.MethodGet || m == http.MethodPost || m == http.MethodPut || m == http.MethodDelete || m == http.MethodPatch || m == http.MethodHead || m == http.MethodOptions {
|
||||
methods = append(methods, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &Info{
|
||||
UUID: e.UUID,
|
||||
Name: e.Name,
|
||||
@@ -85,7 +63,7 @@ func FromEntityInfo(e *api.Info) *Info {
|
||||
Team: e.Team,
|
||||
Creator: e.Creator,
|
||||
Updater: e.Updater,
|
||||
Methods: methods,
|
||||
Methods: e.Method,
|
||||
Protocols: e.Protocol,
|
||||
Path: e.Path,
|
||||
Match: e.Match,
|
||||
@@ -93,26 +71,30 @@ func FromEntityInfo(e *api.Info) *Info {
|
||||
}
|
||||
}
|
||||
|
||||
type CreateAPI struct {
|
||||
type Create struct {
|
||||
UUID string
|
||||
Name string
|
||||
Description string
|
||||
Service string
|
||||
Team string
|
||||
Method string
|
||||
Methods []string
|
||||
Protocols []string
|
||||
Disable bool
|
||||
Path string
|
||||
Match string
|
||||
}
|
||||
|
||||
type EditAPI struct {
|
||||
Name *string
|
||||
Upstream *string
|
||||
type Edit struct {
|
||||
Description *string
|
||||
Methods *[]string
|
||||
Protocols *[]string
|
||||
Disable *bool
|
||||
Path *string
|
||||
Match *string
|
||||
}
|
||||
|
||||
type ExistAPI struct {
|
||||
Path string
|
||||
Method string
|
||||
type Exist struct {
|
||||
Path string
|
||||
Methods []string
|
||||
}
|
||||
|
||||
type Document struct {
|
||||
|
||||
@@ -15,7 +15,7 @@ type IAPIService interface {
|
||||
universally.IServiceDelete
|
||||
CountByService(ctx context.Context, service string) (int64, error)
|
||||
CountMapByService(ctx context.Context, service ...string) (map[string]int64, error)
|
||||
Exist(ctx context.Context, aid string, api *ExistAPI) error
|
||||
Exist(ctx context.Context, aid string, api *Exist) error
|
||||
ListForService(ctx context.Context, serviceId string) ([]*API, error)
|
||||
GetInfo(ctx context.Context, aid string) (*Info, error)
|
||||
ListInfo(ctx context.Context, aids ...string) ([]*Info, error)
|
||||
@@ -25,8 +25,8 @@ type IAPIService interface {
|
||||
GetProxyCommit(ctx context.Context, commitId string) (*commit.Commit[Proxy], error)
|
||||
ListProxyCommit(ctx context.Context, commitId ...string) ([]*commit.Commit[Proxy], error)
|
||||
SaveProxy(ctx context.Context, aid string, data *Proxy) error
|
||||
Save(ctx context.Context, id string, model *EditAPI) error
|
||||
Create(ctx context.Context, input *CreateAPI) (err error)
|
||||
Save(ctx context.Context, id string, model *Edit) error
|
||||
Create(ctx context.Context, input *Create) (err error)
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+2
-2
@@ -8,11 +8,11 @@ import (
|
||||
)
|
||||
|
||||
type IApiBaseStore interface {
|
||||
store.ISearchStore[Api]
|
||||
store.ISearchStore[API]
|
||||
}
|
||||
type IAPIInfoStore store.IBaseStore[Info]
|
||||
type imlApiBaseStore struct {
|
||||
store.SearchStoreSoftDelete[Api]
|
||||
store.SearchStoreSoftDelete[API]
|
||||
}
|
||||
|
||||
type imlAPIDocStore struct {
|
||||
|
||||
+14
-5
@@ -2,7 +2,7 @@ package api
|
||||
|
||||
import "time"
|
||||
|
||||
type Api struct {
|
||||
type API struct {
|
||||
Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"`
|
||||
UUID string `gorm:"type:varchar(36);not null;column:uuid;uniqueIndex:uuid;comment:UUID;"`
|
||||
Name string `gorm:"type:varchar(100);not null;column:name;comment:name"`
|
||||
@@ -12,7 +12,7 @@ type Api struct {
|
||||
Creator string `gorm:"size:36;not null;column:creator;comment:创建人;index:creator" aovalue:"creator"` // 创建人
|
||||
CreateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_at;comment:创建时间"`
|
||||
IsDelete int `gorm:"type:tinyint(1);not null;column:is_delete;comment:是否删除 0:未删除 1:已删除"`
|
||||
Method string `gorm:"size:36;not null;column:method;comment:请求方法"`
|
||||
Method []string `gorm:"size:36;not null;column:method;comment:请求方法;serializer:json"`
|
||||
Protocol []string `gorm:"type:text;not null;column:protocol;comment:协议;serializer:json"`
|
||||
Path string `gorm:"size:512;not null;column:path;comment:请求路径"`
|
||||
}
|
||||
@@ -23,7 +23,7 @@ type Info struct {
|
||||
Description string `gorm:"size:255;not null;column:description;comment:description"`
|
||||
Service string `gorm:"size:36;not null;column:service;comment:服务;index:service"`
|
||||
Team string `gorm:"size:36;not null;column:team;comment:团队;index:team"` // 团队id
|
||||
Method string `gorm:"size:36;not null;column:method;comment:请求方法" `
|
||||
Method []string `gorm:"size:36;not null;column:method;comment:请求方法;serializer:json" `
|
||||
Path string `gorm:"size:512;not null;column:path;comment:请求路径"`
|
||||
Protocol []string `gorm:"type:text;null;column:protocol;comment:协议;serializer:json"`
|
||||
Match string `gorm:"type:text;null;column:match;comment:匹配规则"`
|
||||
@@ -42,10 +42,10 @@ func (i *Info) IdValue() int64 {
|
||||
return i.Id
|
||||
}
|
||||
|
||||
func (a *Api) IdValue() int64 {
|
||||
func (a *API) IdValue() int64 {
|
||||
return a.Id
|
||||
}
|
||||
func (a *Api) TableName() string {
|
||||
func (a *API) TableName() string {
|
||||
return "api"
|
||||
}
|
||||
|
||||
@@ -56,4 +56,13 @@ type Doc struct {
|
||||
Content string `gorm:"type:text;null;column:content;comment:文档内容"`
|
||||
Updater string `gorm:"size:36;not null;column:updater;comment:更新人;index:updater" aovalue:"updater"`
|
||||
UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:update_at;comment:更新时间"`
|
||||
APICount int64 `gorm:"type:int(11);not null;column:api_count;comment:接口数量"`
|
||||
}
|
||||
|
||||
func (i *Doc) TableName() string {
|
||||
return "api_doc"
|
||||
}
|
||||
|
||||
func (i *Doc) IdValue() int64 {
|
||||
return i.Id
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user