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

7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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" {
7 years ago
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)
7 years ago
values ('%s','%d','%s','%s','%d','%s','%d','%d','%d','%d','%s','%d','%s','%d','%s','%d','%s','%d','%s', '%s','%s')`,
7 years ago
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)
7 years ago
_, 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,
})
}
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
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)
7 years ago
res, err := g.DB.Exec(query)
if err != nil {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
}
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("parse api", zap.Error(err), zap.String("api", string(apiR)))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 更新release
7 years ago
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)
7 years ago
_, err = g.DB.Exec(query)
if err != nil {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
}
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
return c.JSON(http.StatusInternalServerError, g.Result{
Status: http.StatusInternalServerError,
ErrCode: g.DatabaseC,
Message: g.DatabaseE,
})
}
// 更新release
7 years ago
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)
7 years ago
_, err = g.DB.Exec(query)
if err != nil {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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 {
7 years ago
g.Info("access database error", zap.Error(err), zap.String("query", query))
7 years ago
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,
})
}