You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

835 lines
25 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package manage
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strconv"
"strings"
"time"
"github.com/mafanr/juz/api/manage/audit"
"github.com/mafanr/juz/misc"
"github.com/mafanr/g"
"github.com/labstack/echo"
"github.com/sunface/talent"
"go.uber.org/zap"
)
/*---------------------API相关-----------------------------*/
func (m *Manage) QueryAPI(c echo.Context) error {
service := talent.FormValue(c, "service")
q := talent.FormValue(c, "q")
pageS := talent.FormValue(c, "page")
if service == "" || pageS == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
page, _ := strconv.Atoi(pageS)
if page <= 0 {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamInvalidC,
Message: g.ParamInvalidE,
})
}
role := talent.FormValue(c, "app_priv")
if !m.canView(role) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
apis := make([]*misc.API, 0)
var query string
if q == "" {
query = fmt.Sprintf("select * from api_define where service='%s' order by modify_date desc limit %d offset %d", service, g.PER_PAGE, g.PER_PAGE*(page-1))
} else {
query = fmt.Sprintf("select * from api_define where service='%s' and ", service) + "api_id like '%" + q + "%' " + fmt.Sprintf(" order by modify_date desc limit %d offset %d", g.PER_PAGE, g.PER_PAGE*(page-1))
}
err := g.DB.Select(&apis, query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
for _, api := range apis {
if api.ParamTable != nil {
d, _ := g.B64.DecodeString(*api.ParamTable)
d1 := talent.Bytes2String(d)
api.ParamTable = &d1
}
}
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
Data: apis,
})
}
func (m *Manage) CountAPI(c echo.Context) error {
service := talent.FormValue(c, "service")
q := talent.FormValue(c, "q")
if service == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
var query string
if q == "" {
query = fmt.Sprintf("select count(1) from api_release where service='%s'", service)
} else {
query = fmt.Sprintf("select count(1) from api_release where service='%s' and api_id like '%%", service) + q + "%'"
}
rows, err := g.DB.Query(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
var total int
rows.Next()
rows.Scan(&total)
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
Data: total,
})
}
func (m *Manage) DefineAPI(c echo.Context) error {
api, ecode, emsg := m.parseAPI(c)
if ecode != 0 {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: ecode,
Message: emsg,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
action := talent.FormValue(c, "action")
now := time.Now()
date := talent.Time2StringSecond(now)
pr := g.B64.EncodeToString(talent.String2Bytes(*api.ParamTable))
if action == "create" {
query := fmt.Sprintf(`insert into api_define (api_id,path_type,service,description,route_type,route_addr,route_proto,bw_strategy,retry_strategy,traffic_strategy,mock_data,traffic_on,traffic_api,traffic_ratio,traffic_ips,verify_on,param_rules,cached_time,revise_version,create_date,app)
values ('%s','%d','%s','%s','%d','%s','%d','%d','%d','%d','%s','%d','%s','%d','%s','%d','%s','%d','%s', '%s','%s')`,
api.APIID, api.PathType, api.Service, *api.Desc, api.RouteType, api.RouteAddr, api.RouteProto, api.BwStrategy, api.RetryStrategy, api.TrafficStrategy, *api.MockData, api.TrafficOn, api.TrafficAPI, api.TrafficRatio, api.TrafficIPs, api.VerifyOn, pr, api.CachedTime, talent.Time2Version(now), date, api.App)
_, err := g.DB.Exec(query)
if err != nil {
if strings.Contains(err.Error(), g.DUP_KEY_ERR) {
return c.JSON(http.StatusConflict, g.Result{
Status: http.StatusConflict,
ErrCode: g.AlreadyExistC,
Message: g.AlreadyExistE,
})
}
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 初始化api发布表并设置为未发布状态
// 这里把不能再修改的值进行初始化
query = fmt.Sprintf(`insert into api_release (api_id,path_type,service,route_addr,status,create_date) values ('%s','%d','%s','%s','%d','%s')`,
api.APIID, api.PathType, api.Service, api.RouteAddr, misc.API_OFFLINE, date)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
audit.Log(c.FormValue("username"), api.Service, audit.TypeApi, api.APIID, audit.OpCreate, c.FormValue("api"), "")
} else {
query := fmt.Sprintf("update api_define set description='%s',route_type='%d',route_addr='%s',route_proto='%d',bw_strategy='%d',retry_strategy='%d',traffic_strategy='%d',mock_data='%s',traffic_on='%d',traffic_api='%s',traffic_ratio='%d',traffic_ips='%s',verify_on='%d',param_rules='%s',cached_time='%d',app='%s' where api_id='%s'",
*api.Desc, api.RouteType, api.RouteAddr, api.RouteProto, api.BwStrategy, api.RetryStrategy, api.TrafficStrategy, *api.MockData, api.TrafficOn, api.TrafficAPI, api.TrafficRatio, api.TrafficIPs, api.VerifyOn, pr, api.CachedTime, api.App, api.APIID)
res, err := g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
n, _ := res.RowsAffected()
if n == 0 {
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
ErrCode: g.NoUpdateHappenedC,
Message: g.NoUpdateHappenedE,
})
}
query = fmt.Sprintf("update api_define set revise_version='%s' where api_id='%s'", talent.Time2Version(now), api.APIID)
g.DB.Exec(query)
audit.Log(c.FormValue("username"), api.Service, audit.TypeApi, api.APIID, audit.OpEdit, c.FormValue("api"), "")
}
// 查询并返回最新的api
api1 := misc.API{}
g.DB.Get(&api1, fmt.Sprintf("select * from api_define where api_id='%s'", api.APIID))
if api1.ParamTable != nil {
d, _ := g.B64.DecodeString(*api1.ParamTable)
d1 := talent.Bytes2String(d)
api1.ParamTable = &d1
}
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
Data: api1,
})
}
// API下线10分钟后方可删除
func (m *Manage) DeleteAPI(c echo.Context) error {
service := talent.FormValue(c, "service")
apiID := talent.FormValue(c, "api_id")
userID := talent.FormValue(c, "username")
if apiID == "" || userID == "" || service == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
// 查询API的发布状态只有下线10分钟后才能删除
query := fmt.Sprintf("select status,modify_date from api_release where api_id='%s'", apiID)
rows, err := g.DB.Query(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
if !rows.Next() {
return c.JSON(http.StatusNotFound, g.Result{
Status: http.StatusNotFound,
ErrCode: APIOfflineC,
Message: APIOfflineE,
})
}
var status int
var ud string
rows.Scan(&status, &ud)
// 已经发布的不能删除
if status == misc.API_RELEASED {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: ApiStillReleasedC,
Message: ApiStillReleasedE,
})
}
// 下线不到30秒不能删除
t, _ := talent.StringToTime(ud)
if time.Now().Sub(t) < 30*time.Second {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: ApiInactiveNotLongEnoughC,
Message: ApiInactiveNotLongEnoughE,
})
}
// 将api发布表的状态设置为已删除
query = fmt.Sprintf("delete from api_release where api_id='%s'", apiID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 查询api定义,为了记录审计日志
api := misc.API{}
query = fmt.Sprintf("select * from api_define where api_id='%s'", apiID)
err = g.DB.Get(&api, query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
}
if api.ParamTable != nil {
d, _ := g.B64.DecodeString(*api.ParamTable)
d1 := talent.Bytes2String(d)
api.ParamTable = &d1
}
b, _ := json.Marshal(api)
// 从api定义表删除
query = fmt.Sprintf("delete from api_define where api_id='%s'", apiID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
audit.Log(userID, service, audit.TypeApi, apiID, audit.OpDelete, talent.Bytes2String(b), "")
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
func (m *Manage) parseAPI(c echo.Context) (*misc.API, int, string) {
apiR := c.FormValue("api")
api := &misc.API{}
err := json.Unmarshal([]byte(apiR), &api)
if err != nil {
g.L.Info("parse api", zap.Error(err), zap.String("api", string(apiR)))
return nil, g.ParamInvalidC, g.ParamInvalidE
}
if api.Service == "" {
return nil, ServiceEmptyC, ServiceEmptyE
}
if api.PathType != misc.OFF && api.PathType != misc.ON {
return nil, ApiPathTypeInvalidC, ApiPathTypeInvalidE
}
if api.PathType == misc.OFF {
// 非路径格式api名组成形式
if !talent.OnlyAlphaNumAndDot(api.APIID) {
return nil, ApiOnlyAlphaNumAndDotC, ApiOnlyAlphaNumAndDotE
}
// 检查api id的前缀
if !strings.HasPrefix(api.APIID, api.Service+".") {
return nil, ApiWithServicePrefixC, ApiWithServicePrefixE
}
} else {
// @todo,检查路径形式的参数是否合法,/a/b/c
//路径不能为保留的
if !talent.OnlyAlphaNumAndUri(api.APIID) {
return nil, ApiOnlyAlphaNumAndUriC, ApiOnlyAlphaNumAndUriE
}
name := api.APIID[:len(api.APIID)-3]
if name == "/service/api" || name == "/notify" {
return nil, ApiReservePathC, ApiReservePathE
}
}
// 检查api id的后缀
if api.APIID[len(api.APIID)-2] != 'v' || api.APIID[len(api.APIID)-3] != '.' {
return nil, ApiWithServiceSuffixC, ApiWithServiceSuffixE
}
if api.RouteAddr == "" || strings.TrimSpace(api.RouteAddr) == "http://" || strings.TrimSpace(api.RouteAddr) == "https://" {
return nil, RouteAddrEmptyC, RouteAddrEmptyE
}
if api.RouteAddr != "" {
if !strings.HasPrefix(api.RouteAddr, "http") {
return nil, RouteAddrWithHTTPPrefixC, RouteAddrWithHTTPPrefixE
}
}
if (api.RouteProto != 1) && (api.RouteProto != 2) {
return nil, RouteProtoInvalidC, RouteProtoInvalidE
}
if api.TrafficAPI != "" {
_, ok := misc.Apis.Load(api.TrafficAPI)
if !ok {
return nil, ApiNotExistC, ApiNotExistE
}
}
if api.TrafficRatio < 0 || api.TrafficRatio > 100 {
return nil, TrafficRatioInvalidC, TrafficRatioInvalidE
}
if (api.TrafficOn != 0) && (api.TrafficOn != 1) {
api.TrafficOn = 0
}
if (api.VerifyOn != 0) && (api.VerifyOn != 1) {
api.VerifyOn = 0
}
if (api.CachedTime < 0) || (api.CachedTime > 30) {
api.CachedTime = 0
}
return api, 0, ""
}
func (m *Manage) APIRelease(c echo.Context) error {
apiID := c.FormValue("api_id")
userID := c.FormValue("username")
if apiID == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
// 查询最新的api定义
api := misc.API{}
query := fmt.Sprintf("select * from api_define where api_id='%s'", apiID)
err := g.DB.Get(&api, query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 更新release
query = fmt.Sprintf("update api_release set description='%s',route_type='%d',route_addr='%s',route_proto='%d',mock_data='%s',retry_strategy='%d',bw_strategy='%d',traffic_strategy='%d',traffic_on='%d',traffic_api='%s',traffic_ratio='%d',traffic_ips='%s',verify_on='%d',param_rules='%s', cached_time='%d',status='%d',app='%s' where api_id='%s'",
*api.Desc, api.RouteType, api.RouteAddr, api.RouteProto, *api.MockData, api.RetryStrategy, api.BwStrategy, api.TrafficStrategy, api.TrafficOn, api.TrafficAPI, api.TrafficRatio, api.TrafficIPs, api.VerifyOn, *api.ParamTable, api.CachedTime, misc.API_RELEASED, api.App, api.APIID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
query = fmt.Sprintf("update api_define set release_version='%s' where api_id='%s'", api.ReviseVersion, api.APIID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
if api.ParamTable != nil {
d, _ := g.B64.DecodeString(*api.ParamTable)
d1 := talent.Bytes2String(d)
api.ParamTable = &d1
}
b, _ := json.Marshal(api)
audit.Log(userID, api.Service, audit.TypeApi, api.APIID, audit.OpRelease, talent.Bytes2String(b), "")
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
func (m *Manage) APIOffline(c echo.Context) error {
apiID := c.FormValue("api_id")
userID := c.FormValue("username")
if apiID == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
query := fmt.Sprintf("update api_release set status='%d' where api_id='%s'",
misc.API_OFFLINE, apiID)
_, err := g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 更新api_define表的发布时间
query = fmt.Sprintf("update api_define set release_version='%s' where api_id='%s'", "", apiID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 查询已发布的api定义
api := misc.API{}
query = fmt.Sprintf("select * from api_release where api_id='%s'", apiID)
err = g.DB.Get(&api, query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
}
if api.ParamTable != nil {
d, _ := g.B64.DecodeString(*api.ParamTable)
d1 := talent.Bytes2String(d)
api.ParamTable = &d1
}
b, _ := json.Marshal(api)
audit.Log(userID, api.Service, audit.TypeApi, api.APIID, audit.OpOffline, talent.Bytes2String(b), "")
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
// 请求参数验证
func (m *Manage) VerifyParamRule(c echo.Context) error {
param := strings.TrimSpace(c.FormValue("param"))
rule := strings.TrimSpace(c.FormValue("rule"))
testData := strings.TrimSpace(c.FormValue("test_data"))
if param == "" || rule == "" || testData == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
// 验证正则是否合法
r, err := regexp.Compile(rule)
if err != nil {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: InvalidVerifyTableC,
Message: InvalidVerifyTableE,
})
}
// 验证测试数据跟正则是否匹配
if !r.Match([]byte(testData)) {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: InvalidVerifyRuleC,
Message: InvalidVerifyRuleE,
})
}
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
//批量设置策略
func (m *Manage) APIBatchStrategy(c echo.Context) error {
apiIDS := strings.TrimSpace(c.FormValue("api_ids"))
bw := strings.TrimSpace(c.FormValue("batch_bw"))
retry := strings.TrimSpace(c.FormValue("batch_retry"))
traffic := strings.TrimSpace(c.FormValue("batch_traffic"))
service := c.FormValue("service")
if apiIDS == "" || (bw == "" && retry == "" && traffic == "") || service == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
var apiIds []string
err := json.Unmarshal([]byte(apiIDS), &apiIds)
if err != nil {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamInvalidC,
Message: g.ParamInvalidE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
now := time.Now()
for _, apiID := range apiIds {
var query = "update api_define set"
if bw != "" {
query = fmt.Sprintf("%s bw_strategy='%s', ", query, bw)
}
if retry != "" {
query = fmt.Sprintf("%s retry_strategy='%s', ", query, retry)
}
if traffic != "" {
query = fmt.Sprintf("%s traffic_strategy='%s'", query, traffic)
}
query = fmt.Sprintf("%s where api_id = '%s'", query, apiID)
res, err := g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
n, _ := res.RowsAffected()
if n == 0 {
continue
}
// 更新版本号
query = fmt.Sprintf("update api_define set revise_version='%s' where api_id='%s'", talent.Time2Version(now), apiID)
g.DB.Exec(query)
}
userID := c.FormValue("username")
audit.Log(userID, service, audit.TypeBatch, fmt.Sprintf("bw: %s,retry: %s", bw, retry), audit.OpCreate, apiIDS, "批量添加策略")
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
// 批量删除策略
func (m *Manage) APIBatchDelStrategy(c echo.Context) error {
apiIDS := strings.TrimSpace(c.FormValue("api_ids"))
service := c.FormValue("service")
if apiIDS == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
var apiIds []string
err := json.Unmarshal([]byte(apiIDS), &apiIds)
if err != nil {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamInvalidC,
Message: g.ParamInvalidE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
tp, _ := strconv.Atoi(c.FormValue("type"))
now := time.Now()
for _, apiID := range apiIds {
var query string
switch tp {
case misc.STRATEGY_BWLIST:
query = fmt.Sprintf("update api_define set bw_strategy='%d' where api_id = '%s'", misc.STRATEGY_EMPTY, apiID)
case misc.STRATEGY_RETRY:
query = fmt.Sprintf("update api_define set retry_strategy='%d' where api_id = '%s'", misc.STRATEGY_EMPTY, apiID)
case misc.STRATEGY_TRAFFIC:
query = fmt.Sprintf("update api_define set traffic_strategy='%d' where api_id = '%s'", misc.STRATEGY_EMPTY, apiID)
default:
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamInvalidC,
Message: g.ParamInvalidE,
})
}
res, err := g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
n, _ := res.RowsAffected()
if n == 0 {
continue
}
// 更新版本号
query = fmt.Sprintf("update api_define set revise_version='%s' where api_id='%s'", talent.Time2Version(now), apiID)
g.DB.Exec(query)
}
userID := c.FormValue("username")
var msg string
switch tp {
case misc.STRATEGY_BWLIST:
msg = "White/Black List"
case misc.STRATEGY_RETRY:
msg = "Timeout/Retry"
case misc.STRATEGY_TRAFFIC:
msg = "Traffic Control"
}
audit.Log(userID, service, audit.TypeBatch, msg, audit.OpDelete, apiIDS, "Batch delete strategy")
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}
func (m *Manage) APIBatchRelease(c echo.Context) error {
apiIDS := strings.TrimSpace(c.FormValue("api_ids"))
if apiIDS == "" {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamEmptyC,
Message: g.ParamEmptyE,
})
}
var apiIds []string
err := json.Unmarshal([]byte(apiIDS), &apiIds)
if err != nil {
return c.JSON(http.StatusBadRequest, g.Result{
Status: http.StatusBadRequest,
ErrCode: g.ParamInvalidC,
Message: g.ParamInvalidE,
})
}
//必须是该service的管理员或者创建者
if !m.canOperate(talent.FormValue(c, "app_priv")) {
return c.JSON(http.StatusForbidden, g.Result{
Status: http.StatusForbidden,
ErrCode: g.ForbiddenC,
Message: g.ForbiddenE,
})
}
for _, apiID := range apiIds {
// 查询最新的api定义
api := misc.API{}
query := fmt.Sprintf("select * from api_define where api_id='%s'", apiID)
err := g.DB.Get(&api, query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 更新release
query = fmt.Sprintf("update api_release set description='%s',route_type='%d',route_addr='%s',route_proto='%d',mock_data='%s',retry_strategy='%d',bw_strategy='%d',traffic_on='%d',traffic_api='%s',traffic_ratio='%d',traffic_ips='%s',verify_on='%d',param_rules='%s', cached_time='%d',status='%d',app='%s' where api_id='%s'",
*api.Desc, api.RouteType, api.RouteAddr, api.RouteProto, *api.MockData, api.RetryStrategy, api.BwStrategy, api.TrafficOn, api.TrafficAPI, api.TrafficRatio, api.TrafficIPs, api.VerifyOn, *api.ParamTable, api.CachedTime, misc.API_RELEASED, api.App, api.APIID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
query = fmt.Sprintf("update api_define set release_version='%s' where api_id='%s'", api.ReviseVersion, api.APIID)
_, err = g.DB.Exec(query)
if err != nil {
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
userID := c.FormValue("username")
if api.ParamTable != nil {
d, _ := g.B64.DecodeString(*api.ParamTable)
d1 := talent.Bytes2String(d)
api.ParamTable = &d1
}
b, _ := json.Marshal(api)
audit.Log(userID, api.Service, audit.TypeApi, api.APIID, audit.OpRelease, talent.Bytes2String(b), "")
}
return c.JSON(http.StatusOK, g.Result{
Status: http.StatusOK,
})
}