作者 yangfu

Merge branch 'test'

/*
1. 查询依赖的查询集
*/
select * from metadata.query_sets where query_set_info->>'BindTableId' in (
select distinct table_id::text from ( /*element_id,table_info,table_type*/
select json_array_elements(to_json(table_info->'dependencyTables'))::text::int element_id,table_info,table_id,table_type
from metadata.tables where table_info->'dependencyTables'::text <>'null' and table_type in ('SubProcess','CalculateTable')
) a where a.element_id in (select table_id from metadata.tables where table_type in ('MainTable','SubTable','SideTable'))
order by table_id asc
) and context->>'operatorId' = '22'
... ...
... ... @@ -26,6 +26,7 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1
github.com/silenceper/wechat/v2 v2.1.4 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
github.com/stretchr/testify v1.7.1
github.com/valyala/fasthttp v1.38.0 // indirect
... ... @@ -46,6 +47,6 @@ require (
replace (
github.com/extrame/xls v0.0.1 => github.com/tiptok/xls v1.0.1
//github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1
github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v1.0.0
github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v1.0.2
)
... ...
... ... @@ -19,10 +19,16 @@ type CreateFileCommand struct {
FileSize int `cname:"文件大小" json:"fileSize" valid:"Required"`
}
var MaxFileSize = 50 * 1024 * 1024
func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validation) {
ext := filepath.Ext(createFileCommand.Name)
if !(ext == domain.XLS || ext == domain.XLSX) {
validation.Error(fmt.Sprintf("仅支持文件格式 xls 、 xlsx"))
validation.Error("仅支持文件格式 xls 、 xlsx")
return
}
if createFileCommand.FileSize > 0 && createFileCommand.FileSize > MaxFileSize {
validation.Error("文件大小超过50M")
return
}
}
... ...
... ... @@ -101,6 +101,9 @@ func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTable
if len(editDataTableCommand.ProcessFields) == 0 {
return nil, factory.FastError(fmt.Errorf("请至少选择一个数据列"))
}
if editDataTableCommand.Action == "remove-column" && len(temporaryFile.Fields) == len(editDataTableCommand.ProcessFields) {
return nil, factory.FastError(fmt.Errorf("请至少保留一个数据列"))
}
// allowAction := func(fields []*domain.Field, action string) error {
// for _, f := range fields {
// if f.SQLType != string(domain.String) &&
... ...
... ... @@ -61,6 +61,12 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
oldFile.FileInfo = fileInfo
oldFile.UpdatedAt = time.Now()
newFile = oldFile
if err = factory.FastLog(transactionContext, domain.CommonLog, oldFile.FileId, &domainService.FileReplaceLog{
LogEntry: domain.NewLogEntry(oldFile.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx),
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
}
file, err := fileRepository.Save(newFile)
... ...
... ... @@ -18,7 +18,10 @@ type AddTableStructCommand struct {
}
func (updateTableCommand *AddTableStructCommand) Valid(validation *validation.Validation) {
if len(updateTableCommand.Fields) == 0 {
validation.Error("请选择字段")
return
}
}
func (updateTableCommand *AddTableStructCommand) ValidateCommand() error {
... ...
... ... @@ -20,9 +20,9 @@ type TablePreviewCommand struct {
}
func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) {
if cmd.UseCache && cmd.PageSize==0{
if cmd.UseCache && cmd.PageSize == 0 {
cmd.PageNumber = 1
cmd.PageSize = 10000 //默认缓存前10000条
cmd.PageSize = 30000 //默认缓存前30000条
}
if cmd.PageSize > 0 {
cmd.Where.PageNumber = cmd.PageNumber
... ...
... ... @@ -18,7 +18,10 @@ type UpdateTableStructCommand struct {
}
func (updateTableCommand *UpdateTableStructCommand) Valid(validation *validation.Validation) {
if len(updateTableCommand.Fields) == 0 {
validation.Error("请选择字段")
return
}
}
func (updateTableCommand *UpdateTableStructCommand) ValidateCommand() error {
... ...
... ... @@ -24,6 +24,7 @@ var (
DeleteTable OperationType = "DeleteTable" // 表删除
FileUpload OperationType = "FileUpload" // 文件上传
FileVerify OperationType = "FileVerify" // 文件校验
FileReplace OperationType = "FileReplace" // 文件替换
ExcelTableEdit OperationType = "ExcelTableEdit" // 文档表格编辑
... ... @@ -58,6 +59,7 @@ var OperationTypeMap = map[string]string{
DeleteTable.ToString(): "表删除",
FileUpload.ToString(): "文件上传",
FileVerify.ToString(): "文件校验",
FileReplace.ToString(): "文件覆盖",
ExcelTableEdit.ToString(): "文档表格编辑",
CreateSchema.ToString(): "新增方案",
... ...
package domain
const (
InvalidAccessToken = 901
InvalidRefreshToken = 902
InvalidSign = 903
InvalidClientId = 904
InvalidUUid = 905
)
var CodeMsg = map[int]string{
InvalidAccessToken: "access token 过期或无效,需刷新令牌",
InvalidRefreshToken: "过期或失效,需重新进行登录认证操作", //refresh token
InvalidSign: "sign 签名无效,需重新登录手机 APP",
InvalidClientId: "client id 或 client secret 无效,需强制更新手机 APP",
InvalidUUid: "uuid 无效",
}
... ...
... ... @@ -273,9 +273,11 @@ func RoundFieldValue(f *Field, v string) string {
return utils.AssertString(fv) //fmt.Sprintf("%v", fv)
}
// TODO:计算表 Count(日期)类型是日期类型,0 的话下面日期解析成当前时间,计算表类型需要修改
if f.SQLType == Datetime.ToString() || f.SQLType == Date.ToString() {
if fv, err := strconv.ParseFloat(v, 64); err == nil {
return utils.AssertString(fv)
}
}
if f.SQLType == Datetime.ToString() {
fv, err := xtime.Parse(v)
if err != nil {
... ...
... ... @@ -47,3 +47,20 @@ func (gateway *ApiAuthLib) MeInfo(param RequestUserMeQuery) (*DataUserMe, error)
}
return &data, nil
}
func (gateway *ApiAuthLib) LoginCheck(param RequestLoginCheck) (*DataLoginCheck, error) {
url := gateway.Host() + "/v1/login/check?token=" + param.Token
method := "get"
var data DataLoginCheck
err := gateway.FastDoRequest(url, method, param, &data, api.WithHeader(gateway.DefaultHeader()))
if errCodeMsg, ok := err.(api.ErrCodeMsg); ok {
return &DataLoginCheck{
Code: errCodeMsg.Code,
Msg: errCodeMsg.Msg,
}, nil
}
if err != nil {
return nil, err
}
return &data, nil
}
... ...
... ... @@ -42,3 +42,11 @@ type DataUserMe struct {
Types string `json:"types"`
} `json:"menus"`
}
type RequestLoginCheck struct {
Token string
}
type DataLoginCheck struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
... ...
... ... @@ -77,6 +77,7 @@ type (
FieldSchema FieldSchema `json:"fieldSchema"`
// 字段新的英文名称(3.汇总集4.计算项中对应的新字段名称)
GroupFieldName string `json:"groupFieldName"`
CalculateExpression string `json:"calculateExpression"`
}
)
... ... @@ -207,6 +208,7 @@ func NewFormulaCalculate(table *domain.Table, queryComponent *domain.QueryCompon
res.FormulaGroupFields = append(res.FormulaGroupFields, &FormulaGroupField{
DatabaseTableName: queryComponent.MasterTable.SQLName,
FieldSchema: NewFieldSchemaFromField(f.Field),
CalculateExpression: f.Expr.ExprSql,
GroupFieldName: tableField.SQLName,
})
}
... ...
... ... @@ -82,6 +82,15 @@ func (ptr *FlushDataTableService) flushSourceFile(ctx *domain.Context, table *do
if err != nil {
return err
}
if len(files) > 0 {
for _, existFile := range files {
if err = FastLog(ptr.transactionContext, domain.CommonLog, file.FileId, &FileReplaceLog{
LogEntry: domain.NewLogEntry(existFile.FileInfo.Name, domain.VerifiedFile.ToString(), domain.FileUpload, ctx),
}); err != nil {
return err
}
}
}
deleteFileService, _ := NewDeleteFileService(ptr.transactionContext)
if err = deleteFileService.DeleteFiles(ctx, files...); err != nil {
return err
... ...
... ... @@ -127,6 +127,15 @@ func (l *FileVerifyLog) Content() string {
return msg
}
// FileReplaceLog 1.1文件已被覆盖
type FileReplaceLog struct {
domain.LogEntry
}
func (l *FileReplaceLog) Content() string {
return fmt.Sprintf("该文件已被覆盖")
}
// GenerateMainTableLog 3.主表生成日志
type GenerateMainTableLog struct {
domain.LogEntry
... ...
... ... @@ -686,6 +686,20 @@ func aggregationHasEdit(ctx *domain.Context, querySet *domain.QuerySet, queryCom
}
func queryComponentsHasEdit(ctx *domain.Context, querySet *domain.QuerySet, queryComponents []*domain.QueryComponent) bool {
if len(querySet.QueryComponents) != len(queryComponents) {
return true
}
for i := range querySet.QueryComponents {
if querySet.QueryComponents[i].MasterTable == nil || queryComponents[i].MasterTable == nil {
continue
}
if querySet.QueryComponents[i].MasterTable.TableId != queryComponents[i].MasterTable.TableId {
return true
}
if len(querySet.QueryComponents[i].MasterTable.Fields) != len(queryComponents[i].MasterTable.Fields) {
return true
}
}
logs := selectsEditLog(ctx, querySet, queryComponents)
if len(logs) > 0 {
return true
... ...
... ... @@ -445,7 +445,7 @@ func (d *DataLayoutDataTable) Expand(cell *domain.LayoutCell, length int) error
if expandLength < length {
expandLength = length
}
if d.MaxX+expandLength > MaxExpandNum {
if d.MaxX+expandLength > MaxExpandNum+DefaultExpandNum {
return fmt.Errorf("布局元素超过限制 %d", MaxExpandNum)
}
copyData := make([][]string, d.MaxX+length)
... ...
... ... @@ -171,7 +171,7 @@ func (repository *QuerySetRepository) Find(queryOptions map[string]interface{})
query.Where("query_set_info->'BindTableId' in (?)", pg.In(utils.ToArrayString(v.([]int))))
}
if v, ok := queryOptions["sortByName"]; ok && len(v.(string)) > 0 {
query.SetOrderDirect("pin_name", v.(string))
query.SetOrderDirect("name", v.(string))//pin_name
} else if v, ok := queryOptions["sortByTime"]; ok && len(v.(string)) > 0 {
query.SetOrderDirect("created_at", v.(string))
} else {
... ...
... ... @@ -8,6 +8,7 @@ import (
"github.com/linmadan/egglib-go/web/beego/filters"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/authlib"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers"
"net/http"
"os"
... ... @@ -76,6 +77,9 @@ func CreateRequestLogFilter(console bool) func(ctx *context.Context) {
}
func JwtFilter() func(ctx *context.Context) {
authLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST)
authLib.BaseServiceGateway.ConnectTimeout = 200 * time.Millisecond
authLib.BaseServiceGateway.ReadWriteTimeout = 200 * time.Millisecond
return func(ctx *context.Context) {
//token := ctx.Request.Header.Get("Authorization")
token := ctx.Request.Header.Get("x-mmm-accesstoken")
... ... @@ -85,17 +89,35 @@ func JwtFilter() func(ctx *context.Context) {
err := userToken.ParseToken(token)
if err != nil {
ctx.Output.SetStatus(http.StatusOK)
ctx.Output.JSON(map[string]interface{}{
"msg": "token 过期或无效,需刷新令牌",
"code": 901,
"data": struct{}{},
}, false, false)
ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false)
return
}
if userToken.UserId > 0 && userToken.CompanyId > 0 {
loginCheckResponse, _ := authLib.LoginCheck(authlib.RequestLoginCheck{Token: token})
if loginCheckResponse != nil && loginCheckResponse.Code == 901 {
ctx.Output.SetStatus(http.StatusOK)
ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false)
return
}
}
ctx.Input.SetData("UserToken", userToken)
ctx.Input.SetData("Accesstoken", token)
}
}
}
func WithCodeMsgResponse(code int) map[string]interface{} {
msg := "token 过期或无效,需刷新令牌"
if codeMsg, ok := domain.CodeMsg[code]; ok {
msg = codeMsg
}
return map[string]interface{}{
"msg": msg,
"code": code,
"data": struct{}{},
}
}
func RequestCostBefore() func(ctx *context.Context) {
return func(ctx *context.Context) {
ctx.Input.SetData("cost-begin", time.Now().UnixMilli())
... ...
... ... @@ -57,7 +57,11 @@ func ParseContext(c beego.BaseController) *domain.Context {
v := cacheItem.(*authlib.DataUserMe)
userName = v.User.NickName
} else {
requestToken, _ := userToken.GenerateToken()
//requestToken, _ := userToken.GenerateToken()
requestToken, ok := c.Ctx.Input.GetData("Accesstoken").(string)
if !ok {
goto END
}
authLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST).WithToken(requestToken)
userInfo, err := authLib.MeInfo(authlib.RequestUserMeQuery{
UserId: int(userToken.UserId),
... ...
package controllers
import (
_ "embed"
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/utils/json"
"strings"
)
//go:embed errors.txt
var errorsData []byte
type CommErrorResolver struct {
// TODO:LRU latest error list
ErrorMapping map[string]string `json:"errorMapping"`
errMapping map[string]error `json:"errorMapping"`
}
func (r *CommErrorResolver) Resolve(err error) error {
if err == nil {
return nil
}
errMsg := err.Error()
if r.errMapping == nil {
return err
}
if v, ok := r.errMapping[errMsg]; ok {
return v
}
for k, v := range r.errMapping {
if strings.Contains(errMsg, k) {
return v
}
}
return err
}
func NewCommErrorResolver() (*CommErrorResolver, error) {
obj := &CommErrorResolver{errMapping: make(map[string]error)}
err := json.Unmarshal(errorsData, obj)
if err != nil {
return nil, err
}
for k, v := range obj.ErrorMapping {
obj.errMapping[k] = application.ThrowError(application.INTERNAL_SERVER_ERROR, v)
}
return obj, nil
}
... ...
{
"errorMapping":{
"Backend not found. Check if any backend is down or not":"数据库服务繁忙"
}
}
\ No newline at end of file
... ...
... ... @@ -6,37 +6,39 @@ import (
)
func init() {
web.Router("/data/tables/", &controllers.TableController{}, "Post:CreateTable")
//web.Router("/data/tables/:tableId", &controllers.TableController{}, "Put:UpdateTable")
web.Router("/data/tables/:tableId", &controllers.TableController{}, "Get:GetTable")
web.Router("/data/tables/prepare", &controllers.TableController{}, "Get:PrepareTable")
web.Router("/data/tables/:tableId", &controllers.TableController{}, "Delete:RemoveTable")
web.Router("/data/tables/", &controllers.TableController{}, "Get:ListTable")
web.Router("/data/tables/search", &controllers.TableController{}, "Post:Search")
web.Router("/data/tables/relation-graph", &controllers.TableController{}, "Post:RelationGraph")
web.Router("/data/tables/apply-on", &controllers.TableController{}, "Post:ApplyOn")
web.Router("/data/tables/valid-expr-sql", &controllers.TableController{}, "Post:ValidExprSql")
web.Router("/data/tables/check", &controllers.TableController{}, "Post:CheckRowDuplicate")
web.Router("/data/tables/check-row-value-duplicate", &controllers.TableController{}, "Post:CheckRowValueDuplicate")
web.Router("/data/tables/search-appended-list", &controllers.TableController{}, "Post:SearchAppendedList")
web.Router("/data/tables/search-sub-table-list", &controllers.TableController{}, "Post:SearchSubTableList")
web.Router("/data/tables/search-query-set-tables", &controllers.TableController{}, "Post:SearchQuerySetTables")
web.Router("/data/tables/dependency-graph", &controllers.TableController{}, "Post:DependencyGraph")
tableController := &controllers.TableController{}
tableController.BaseController.ErrorResolver, _ = controllers.NewCommErrorResolver()
web.Router("/data/tables/", tableController, "Post:CreateTable")
//web.Router("/data/tables/:tableId", tableController, "Put:UpdateTable")
web.Router("/data/tables/:tableId", tableController, "Get:GetTable")
web.Router("/data/tables/prepare", tableController, "Get:PrepareTable")
web.Router("/data/tables/:tableId", tableController, "Delete:RemoveTable")
web.Router("/data/tables/", tableController, "Get:ListTable")
web.Router("/data/tables/search", tableController, "Post:Search")
web.Router("/data/tables/relation-graph", tableController, "Post:RelationGraph")
web.Router("/data/tables/apply-on", tableController, "Post:ApplyOn")
web.Router("/data/tables/valid-expr-sql", tableController, "Post:ValidExprSql")
web.Router("/data/tables/check", tableController, "Post:CheckRowDuplicate")
web.Router("/data/tables/check-row-value-duplicate", tableController, "Post:CheckRowValueDuplicate")
web.Router("/data/tables/search-appended-list", tableController, "Post:SearchAppendedList")
web.Router("/data/tables/search-sub-table-list", tableController, "Post:SearchSubTableList")
web.Router("/data/tables/search-query-set-tables", tableController, "Post:SearchQuerySetTables")
web.Router("/data/tables/dependency-graph", tableController, "Post:DependencyGraph")
//web.Router("/data/tables/split-data-table", &controllers.TableController{}, "Post:SplitDataTable")
//web.Router("/data/tables/batch-edit-sub-table", &controllers.TableController{}, "Post:BatchEditSubTable")
web.Router("/data/tables/copy-data-table", &controllers.TableController{}, "Post:CopyDataTable")
web.Router("/data/tables/update-table-struct/:tableId", &controllers.TableController{}, "Put:UpdateTableStruct")
web.Router("/data/tables/add-sub-table", &controllers.TableController{}, "Post:AddTableStruct")
web.Router("/data/tables/export-table", &controllers.TableController{}, "Post:ExportDataTable")
//web.Router("/data/tables/split-data-table", tableController, "Post:SplitDataTable")
//web.Router("/data/tables/batch-edit-sub-table", tableController, "Post:BatchEditSubTable")
web.Router("/data/tables/copy-data-table", tableController, "Post:CopyDataTable")
web.Router("/data/tables/update-table-struct/:tableId", tableController, "Put:UpdateTableStruct")
web.Router("/data/tables/add-sub-table", tableController, "Post:AddTableStruct")
web.Router("/data/tables/export-table", tableController, "Post:ExportDataTable")
web.Router("/data/tables/table-preview", &controllers.TableController{}, "Post:TablePreview")
web.Router("/data/tables/row-edit", &controllers.TableController{}, "Post:RowEdit")
web.Router("/data/tables/table-preview", tableController, "Post:TablePreview")
web.Router("/data/tables/row-edit", tableController, "Post:RowEdit")
web.Router("/data/field-optional-values", &controllers.TableController{}, "Post:FieldOptionalValues")
web.Router("/data/table-object-search", &controllers.TableController{}, "Post:TableObjectSearch")
web.Router("/data/field-optional-values", tableController, "Post:FieldOptionalValues")
web.Router("/data/table-object-search", tableController, "Post:TableObjectSearch")
web.Router("/business/db-table-preview", &controllers.TableController{}, "Post:DBTablePreview")
web.Router("/data/table-preview", &controllers.TableController{}, "Post:Preview")
web.Router("/business/db-table-preview", tableController, "Post:DBTablePreview")
web.Router("/data/table-preview", tableController, "Post:Preview")
}
... ...