From 9bd2934e42b930157ec085108a90e0294264bab0 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 25 Oct 2020 21:07:03 +0800 Subject: [PATCH 01/31] add order clause --- client/orm/db_tables.go | 13 ++++---- client/orm/orm.go | 3 +- client/orm/orm_queryset.go | 11 ++++--- client/orm/structs/order_phrase.go | 48 ++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 client/orm/structs/order_phrase.go diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 5fd472d1..c67af052 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -16,6 +16,7 @@ package orm import ( "fmt" + "github.com/astaxie/beego/client/orm/structs" "strings" "time" ) @@ -421,7 +422,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) { } // generate order sql. -func (t *dbTables) getOrderSQL(orders []string) (orderSQL string) { +func (t *dbTables) getOrderSQL(orders []*structs.OrderClause) (orderSQL string) { if len(orders) == 0 { return } @@ -430,16 +431,16 @@ func (t *dbTables) getOrderSQL(orders []string) (orderSQL string) { orderSqls := make([]string, 0, len(orders)) for _, order := range orders { + column := order.Column asc := "ASC" - if order[0] == '-' { + if order.Sort == structs.DESCENDING { asc = "DESC" - order = order[1:] } - exprs := strings.Split(order, ExprSep) + clause := strings.Split(column, ExprSep) - index, _, fi, suc := t.parseExprs(t.mi, exprs) + index, _, fi, suc := t.parseExprs(t.mi, clause) if !suc { - panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep))) + panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) } orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, asc)) diff --git a/client/orm/orm.go b/client/orm/orm.go index a83faeb2..52a99572 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -58,6 +58,7 @@ import ( "database/sql" "errors" "fmt" + "github.com/astaxie/beego/client/orm/structs" "os" "reflect" "time" @@ -351,7 +352,7 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s qs.relDepth = relDepth if len(order) > 0 { - qs.orders = []string{order} + qs.orders = structs.ParseOrderClause(order) } find := ind.FieldByIndex(fi.fieldIndex) diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index ed223e24..480dc561 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -17,8 +17,8 @@ package orm import ( "context" "fmt" - "github.com/astaxie/beego/client/orm/hints" + "github.com/astaxie/beego/client/orm/structs" ) type colValue struct { @@ -71,7 +71,7 @@ type querySet struct { limit int64 offset int64 groups []string - orders []string + orders []*structs.OrderClause distinct bool forUpdate bool useIndex int @@ -139,8 +139,11 @@ func (o querySet) GroupBy(exprs ...string) QuerySeter { // add ORDER expression. // "column" means ASC, "-column" means DESC. -func (o querySet) OrderBy(exprs ...string) QuerySeter { - o.orders = exprs +func (o querySet) OrderBy(expressions ...string) QuerySeter { + if len(expressions) <= 0 { + return &o + } + o.orders = structs.ParseOrderClause(expressions...) return &o } diff --git a/client/orm/structs/order_phrase.go b/client/orm/structs/order_phrase.go new file mode 100644 index 00000000..30faf429 --- /dev/null +++ b/client/orm/structs/order_phrase.go @@ -0,0 +1,48 @@ +package structs + +import "fmt" + +type Sort int8 + +const ( + ASCENDING Sort = 1 + DESCENDING Sort = 2 +) + +type OrderClause struct { + Column string + Sort Sort +} + +var _ fmt.Stringer = new(OrderClause) + +func (o *OrderClause) String() string { + sort := `` + if o.Sort == ASCENDING { + sort = `ASC` + } else if o.Sort == DESCENDING { + sort = `DESC` + } else { + return fmt.Sprintf("%s", o.Column) + } + return fmt.Sprintf("%s %s", o.Column, sort) +} + +func ParseOrderClause(expressions ...string) []*OrderClause { + var orders []*OrderClause + for _, expression := range expressions { + sort := ASCENDING + column := expression + if expression[0] == '-' { + sort = DESCENDING + column = expression[1:] + } + + orders = append(orders, &OrderClause{ + Column: column, + Sort: sort, + }) + } + + return orders +} From 544c621017dd82aa184bced157cb82fe201a0f4a Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 25 Oct 2020 23:11:05 +0800 Subject: [PATCH 02/31] move dir & delete some useless function --- client/orm/db_tables.go | 17 +++++----- client/orm/orm.go | 4 +-- client/orm/orm_conds.go | 3 +- client/orm/orm_queryset.go | 6 ++-- client/orm/structs/clauses/const.go | 5 +++ client/orm/structs/clauses/order.go | 40 ++++++++++++++++++++++++ client/orm/structs/order_phrase.go | 48 ----------------------------- 7 files changed, 62 insertions(+), 61 deletions(-) create mode 100644 client/orm/structs/clauses/const.go create mode 100644 client/orm/structs/clauses/order.go delete mode 100644 client/orm/structs/order_phrase.go diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index c67af052..7c6e6fff 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -16,7 +16,7 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/structs/clauses" "strings" "time" ) @@ -422,7 +422,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) { } // generate order sql. -func (t *dbTables) getOrderSQL(orders []*structs.OrderClause) (orderSQL string) { +func (t *dbTables) getOrderSQL(orders []*clauses.Order) (orderSQL string) { if len(orders) == 0 { return } @@ -431,10 +431,13 @@ func (t *dbTables) getOrderSQL(orders []*structs.OrderClause) (orderSQL string) orderSqls := make([]string, 0, len(orders)) for _, order := range orders { - column := order.Column - asc := "ASC" - if order.Sort == structs.DESCENDING { - asc = "DESC" + column := order.GetColumn() + var sort string + switch order.GetSort() { + case clauses.ASCENDING: + sort = "ASC" + case clauses.DESCENDING: + sort = "DESC" } clause := strings.Split(column, ExprSep) @@ -443,7 +446,7 @@ func (t *dbTables) getOrderSQL(orders []*structs.OrderClause) (orderSQL string) panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) } - orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, asc)) + orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, sort)) } orderSQL = fmt.Sprintf("ORDER BY %s ", strings.Join(orderSqls, ", ")) diff --git a/client/orm/orm.go b/client/orm/orm.go index 52a99572..d1a66b88 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -58,7 +58,7 @@ import ( "database/sql" "errors" "fmt" - "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/structs/clauses" "os" "reflect" "time" @@ -352,7 +352,7 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s qs.relDepth = relDepth if len(order) > 0 { - qs.orders = structs.ParseOrderClause(order) + qs.orders = clauses.ParseOrder(order) } find := ind.FieldByIndex(fi.fieldIndex) diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index f3fd66f0..7a798c6f 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -16,12 +16,13 @@ package orm import ( "fmt" + "github.com/astaxie/beego/client/orm/structs/clauses" "strings" ) // ExprSep define the expression separation const ( - ExprSep = "__" + ExprSep = clauses.ExprSep ) type condValue struct { diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 480dc561..5ca10421 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -18,7 +18,7 @@ import ( "context" "fmt" "github.com/astaxie/beego/client/orm/hints" - "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/structs/clauses" ) type colValue struct { @@ -71,7 +71,7 @@ type querySet struct { limit int64 offset int64 groups []string - orders []*structs.OrderClause + orders []*clauses.Order distinct bool forUpdate bool useIndex int @@ -143,7 +143,7 @@ func (o querySet) OrderBy(expressions ...string) QuerySeter { if len(expressions) <= 0 { return &o } - o.orders = structs.ParseOrderClause(expressions...) + o.orders = clauses.ParseOrder(expressions...) return &o } diff --git a/client/orm/structs/clauses/const.go b/client/orm/structs/clauses/const.go new file mode 100644 index 00000000..a0574a64 --- /dev/null +++ b/client/orm/structs/clauses/const.go @@ -0,0 +1,5 @@ +package clauses + +const ( + ExprSep = "__" +) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go new file mode 100644 index 00000000..050bcf1b --- /dev/null +++ b/client/orm/structs/clauses/order.go @@ -0,0 +1,40 @@ +package clauses + +type Sort int8 + +const ( + ASCENDING Sort = 1 + DESCENDING Sort = 2 +) + +type Order struct { + column string + sort Sort +} + +func (o *Order) GetColumn() string { + return o.column +} + +func (o *Order) GetSort() Sort { + return o.sort +} + +func ParseOrder(expressions ...string) []*Order { + var orders []*Order + for _, expression := range expressions { + sort := ASCENDING + column := expression + if expression[0] == '-' { + sort = DESCENDING + column = expression[1:] + } + + orders = append(orders, &Order{ + column: column, + sort: sort, + }) + } + + return orders +} diff --git a/client/orm/structs/order_phrase.go b/client/orm/structs/order_phrase.go deleted file mode 100644 index 30faf429..00000000 --- a/client/orm/structs/order_phrase.go +++ /dev/null @@ -1,48 +0,0 @@ -package structs - -import "fmt" - -type Sort int8 - -const ( - ASCENDING Sort = 1 - DESCENDING Sort = 2 -) - -type OrderClause struct { - Column string - Sort Sort -} - -var _ fmt.Stringer = new(OrderClause) - -func (o *OrderClause) String() string { - sort := `` - if o.Sort == ASCENDING { - sort = `ASC` - } else if o.Sort == DESCENDING { - sort = `DESC` - } else { - return fmt.Sprintf("%s", o.Column) - } - return fmt.Sprintf("%s %s", o.Column, sort) -} - -func ParseOrderClause(expressions ...string) []*OrderClause { - var orders []*OrderClause - for _, expression := range expressions { - sort := ASCENDING - column := expression - if expression[0] == '-' { - sort = DESCENDING - column = expression[1:] - } - - orders = append(orders, &OrderClause{ - Column: column, - Sort: sort, - }) - } - - return orders -} From b1d5ba8ece68900ce448cf8cd79fc42f76ccdda0 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 25 Oct 2020 23:16:41 +0800 Subject: [PATCH 03/31] support sort none --- client/orm/db_tables.go | 4 ++-- client/orm/structs/clauses/order.go | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 7c6e6fff..5c330f4e 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -434,9 +434,9 @@ func (t *dbTables) getOrderSQL(orders []*clauses.Order) (orderSQL string) { column := order.GetColumn() var sort string switch order.GetSort() { - case clauses.ASCENDING: + case clauses.SortAscending: sort = "ASC" - case clauses.DESCENDING: + case clauses.SortDescending: sort = "DESC" } clause := strings.Split(column, ExprSep) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go index 050bcf1b..66e8fe73 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order.go @@ -3,8 +3,9 @@ package clauses type Sort int8 const ( - ASCENDING Sort = 1 - DESCENDING Sort = 2 + SortNone Sort = 0 + SortAscending Sort = 1 + SortDescending Sort = 2 ) type Order struct { @@ -23,10 +24,10 @@ func (o *Order) GetSort() Sort { func ParseOrder(expressions ...string) []*Order { var orders []*Order for _, expression := range expressions { - sort := ASCENDING + sort := SortAscending column := expression if expression[0] == '-' { - sort = DESCENDING + sort = SortDescending column = expression[1:] } From 56fa213a6edf0c9ae0421ebf59683cbe6c41c8ca Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 25 Oct 2020 23:49:21 +0800 Subject: [PATCH 04/31] support OrderClauses for QuerySeter --- client/orm/orm_queryset.go | 9 +++++++ client/orm/structs/clauses/order.go | 34 ++++++++++++++++++++++++ client/orm/structs/clauses/order_test.go | 29 ++++++++++++++++++++ client/orm/types.go | 19 +++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 client/orm/structs/clauses/order_test.go diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 5ca10421..e6493d8f 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -147,6 +147,15 @@ func (o querySet) OrderBy(expressions ...string) QuerySeter { return &o } +// add ORDER expression. +func (o querySet) OrderClauses(orders ...*clauses.Order) QuerySeter { + if len(orders) <= 0 { + return &o + } + o.orders = orders + return &o +} + // add DISTINCT to SELECT func (o querySet) Distinct() QuerySeter { o.distinct = true diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go index 66e8fe73..64e4ebbd 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order.go @@ -8,9 +8,21 @@ const ( SortDescending Sort = 2 ) +type OrderOption func(order *Order) + type Order struct { column string sort Sort + isRaw bool +} + +func OrderClause(options ...OrderOption) *Order { + o := &Order{} + for _, option := range options { + option(o) + } + + return o } func (o *Order) GetColumn() string { @@ -21,6 +33,10 @@ func (o *Order) GetSort() Sort { return o.sort } +func (o *Order) IsRaw() bool { + return o.isRaw +} + func ParseOrder(expressions ...string) []*Order { var orders []*Order for _, expression := range expressions { @@ -39,3 +55,21 @@ func ParseOrder(expressions ...string) []*Order { return orders } + +func OrderColumn(column string) OrderOption { + return func(order *Order) { + order.column = column + } +} + +func OrderSort(sort Sort) OrderOption { + return func(order *Order) { + order.sort = sort + } +} + +func OrderRaw(isRaw bool) OrderOption { + return func(order *Order) { + order.isRaw = isRaw + } +} diff --git a/client/orm/structs/clauses/order_test.go b/client/orm/structs/clauses/order_test.go new file mode 100644 index 00000000..2f44975d --- /dev/null +++ b/client/orm/structs/clauses/order_test.go @@ -0,0 +1,29 @@ +package clauses + +import "testing" + +func TestOrderClause(t *testing.T) { + var ( + column = `a` + sort = SortDescending + raw = true + ) + + o := OrderClause( + OrderColumn(column), + OrderSort(sort), + OrderRaw(raw), + ) + + if o.GetColumn() != column { + t.Error() + } + + if o.GetSort() != sort { + t.Error() + } + + if o.IsRaw() != raw { + t.Error() + } +} diff --git a/client/orm/types.go b/client/orm/types.go index 34c61d51..f1d6def7 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -17,6 +17,7 @@ package orm import ( "context" "database/sql" + "github.com/astaxie/beego/client/orm/structs/clauses" "reflect" "time" @@ -289,6 +290,24 @@ type QuerySeter interface { // for example: // qs.OrderBy("-status") OrderBy(exprs ...string) QuerySeter + // add ORDER expression by order clauses + // for example: + // OrderClauses(clauses.OrderClause( + // clauses.OrderColumn(`status`), + // clauses.OrderSort(clauses.SortAscending), + // clauses.OrderRaw(false), + // )) + // OrderClauses(clauses.OrderClause( + // clauses.OrderColumn(`user__status`), + // clauses.OrderSort(clauses.SortAscending), + // clauses.OrderRaw(false), + // )) + // OrderClauses(clauses.OrderClause( + // clauses.OrderColumn(`random()`), + // clauses.OrderSort(clauses.SortNone), + // clauses.OrderRaw(true), + // )) + OrderClauses(orders ...*clauses.Order) QuerySeter // add FORCE INDEX expression. // for example: // qs.ForceIndex(`idx_name1`,`idx_name2`) From 7d4e88c1b951db2ac778feaf02ac530ff171c212 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Mon, 26 Oct 2020 00:01:15 +0800 Subject: [PATCH 05/31] support raw order --- client/orm/db_tables.go | 29 ++++++++++++++++------------- client/orm/structs/clauses/const.go | 1 + client/orm/structs/clauses/order.go | 20 +++++++++++++++++--- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 5c330f4e..34fa0f07 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -432,21 +432,24 @@ func (t *dbTables) getOrderSQL(orders []*clauses.Order) (orderSQL string) { orderSqls := make([]string, 0, len(orders)) for _, order := range orders { column := order.GetColumn() - var sort string - switch order.GetSort() { - case clauses.SortAscending: - sort = "ASC" - case clauses.SortDescending: - sort = "DESC" - } - clause := strings.Split(column, ExprSep) + clause := strings.Split(column, clauses.ExprDot) - index, _, fi, suc := t.parseExprs(t.mi, clause) - if !suc { - panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) - } + if order.IsRaw() { + if len(clause) == 2 { + orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", clause[0], Q, clause[1], Q, order.SortString())) + } else if len(clause) == 1 { + orderSqls = append(orderSqls, fmt.Sprintf("%s%s%s %s", Q, clause[0], Q, order.SortString())) + } else { + panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) + } + } else { + index, _, fi, suc := t.parseExprs(t.mi, clause) + if !suc { + panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(clause, ExprSep))) + } - orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, sort)) + orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, order.SortString())) + } } orderSQL = fmt.Sprintf("ORDER BY %s ", strings.Join(orderSqls, ", ")) diff --git a/client/orm/structs/clauses/const.go b/client/orm/structs/clauses/const.go index a0574a64..747d3fd7 100644 --- a/client/orm/structs/clauses/const.go +++ b/client/orm/structs/clauses/const.go @@ -2,4 +2,5 @@ package clauses const ( ExprSep = "__" + ExprDot = "." ) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go index 64e4ebbd..2f7ff6ba 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order.go @@ -1,5 +1,7 @@ package clauses +import "strings" + type Sort int8 const ( @@ -33,6 +35,18 @@ func (o *Order) GetSort() Sort { return o.sort } +func (o *Order) SortString() string { + switch o.GetSort() { + case SortAscending: + return "ASC" + case SortDescending: + return "DESC" + } + + return `` +} + + func (o *Order) IsRaw() bool { return o.isRaw } @@ -41,10 +55,10 @@ func ParseOrder(expressions ...string) []*Order { var orders []*Order for _, expression := range expressions { sort := SortAscending - column := expression - if expression[0] == '-' { + column := strings.ReplaceAll(expression, ExprSep, ExprDot) + if column[0] == '-' { sort = SortDescending - column = expression[1:] + column = column[1:] } orders = append(orders, &Order{ From d24388ad819916bf1bea2920f0bd8577c4cb3ea9 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Mon, 26 Oct 2020 18:57:01 +0800 Subject: [PATCH 06/31] opt Methods --- client/orm/structs/clauses/order.go | 19 +++++-- client/orm/structs/clauses/order_test.go | 67 +++++++++++++++++++++--- client/orm/types.go | 10 ++-- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go index 2f7ff6ba..e1110eec 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order.go @@ -46,7 +46,6 @@ func (o *Order) SortString() string { return `` } - func (o *Order) IsRaw() bool { return o.isRaw } @@ -76,14 +75,26 @@ func OrderColumn(column string) OrderOption { } } -func OrderSort(sort Sort) OrderOption { +func sort(sort Sort) OrderOption { return func(order *Order) { order.sort = sort } } -func OrderRaw(isRaw bool) OrderOption { +func OrderSortAscending() OrderOption { + return sort(SortAscending) +} + +func OrderSortDescending() OrderOption { + return sort(SortDescending) +} + +func OrderSortNone() OrderOption { + return sort(SortNone) +} + +func OrderRaw() OrderOption { return func(order *Order) { - order.isRaw = isRaw + order.isRaw = true } } diff --git a/client/orm/structs/clauses/order_test.go b/client/orm/structs/clauses/order_test.go index 2f44975d..dbb37a0a 100644 --- a/client/orm/structs/clauses/order_test.go +++ b/client/orm/structs/clauses/order_test.go @@ -5,25 +5,76 @@ import "testing" func TestOrderClause(t *testing.T) { var ( column = `a` - sort = SortDescending - raw = true ) o := OrderClause( OrderColumn(column), - OrderSort(sort), - OrderRaw(raw), ) if o.GetColumn() != column { t.Error() } +} - if o.GetSort() != sort { - t.Error() - } +func TestOrderSortAscending(t *testing.T) { + o := OrderClause( + OrderSortAscending(), + ) - if o.IsRaw() != raw { + if o.GetSort() != SortAscending { t.Error() } } + +func TestOrderSortDescending(t *testing.T) { + o := OrderClause( + OrderSortDescending(), + ) + + if o.GetSort() != SortDescending { + t.Error() + } +} + +func TestOrderSortNone(t *testing.T) { + o1 := OrderClause( + OrderSortNone(), + ) + + if o1.GetSort() != SortNone { + t.Error() + } + + o2 := OrderClause() + + if o2.GetSort() != SortNone { + t.Error() + } +} + +func TestOrderRaw(t *testing.T) { + o1 := OrderClause() + + if o1.IsRaw() { + t.Error() + } + + o2 := OrderClause( + OrderRaw(), + ) + + if !o2.IsRaw() { + t.Error() + } +} + +func TestOrderColumn(t *testing.T) { + o1 := OrderClause( + OrderColumn(`aaa`), + ) + + if o1.GetColumn() != `aaa` { + t.Error() + } +} + diff --git a/client/orm/types.go b/client/orm/types.go index f1d6def7..14a34025 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -294,18 +294,16 @@ type QuerySeter interface { // for example: // OrderClauses(clauses.OrderClause( // clauses.OrderColumn(`status`), - // clauses.OrderSort(clauses.SortAscending), - // clauses.OrderRaw(false), + // clauses.OrderSortAscending(),//default None // )) // OrderClauses(clauses.OrderClause( // clauses.OrderColumn(`user__status`), - // clauses.OrderSort(clauses.SortAscending), - // clauses.OrderRaw(false), + // clauses.OrderSortDescending(),//default None // )) // OrderClauses(clauses.OrderClause( // clauses.OrderColumn(`random()`), - // clauses.OrderSort(clauses.SortNone), - // clauses.OrderRaw(true), + // clauses.OrderSortNone(),//default None + // clauses.OrderRaw(),//default false.if true, do not check field is valid or not // )) OrderClauses(orders ...*clauses.Order) QuerySeter // add FORCE INDEX expression. From beedfa1b53d1847f6cb1f31b0cafac184fbee156 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Mon, 26 Oct 2020 19:52:21 +0800 Subject: [PATCH 07/31] add UT --- client/orm/orm_test.go | 34 +++++++++++++++++++++++++++++ client/orm/structs/clauses/order.go | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index 565f6c60..8f057df1 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -21,6 +21,7 @@ import ( "context" "database/sql" "fmt" + "github.com/astaxie/beego/client/orm/structs/clauses" "io/ioutil" "math" "os" @@ -1077,6 +1078,26 @@ func TestOrderBy(t *testing.T) { num, err = qs.OrderBy("-profile__age").Filter("user_name", "astaxie").Count() throwFail(t, err) throwFail(t, AssertIs(num, 1)) + + num, err = qs.OrderClauses( + clauses.OrderClause( + clauses.OrderColumn(`profile__age`), + clauses.OrderSortDescending(), + ), + ).Filter("user_name", "astaxie").Count() + throwFail(t, err) + throwFail(t, AssertIs(num, 1)) + + if IsMysql { + num, err = qs.OrderClauses( + clauses.OrderClause( + clauses.OrderColumn(`rand()`), + clauses.OrderRaw(), + ), + ).Filter("user_name", "astaxie").Count() + throwFail(t, err) + throwFail(t, AssertIs(num, 1)) + } } func TestAll(t *testing.T) { @@ -1163,6 +1184,19 @@ func TestValues(t *testing.T) { throwFail(t, AssertIs(maps[2]["Profile"], nil)) } + num, err = qs.OrderClauses( + clauses.OrderClause( + clauses.OrderColumn("Id"), + clauses.OrderSortAscending(), + ), + ).Values(&maps) + throwFail(t, err) + throwFail(t, AssertIs(num, 3)) + if num == 3 { + throwFail(t, AssertIs(maps[0]["UserName"], "slene")) + throwFail(t, AssertIs(maps[2]["Profile"], nil)) + } + num, err = qs.OrderBy("Id").Values(&maps, "UserName", "Profile__Age") throwFail(t, err) throwFail(t, AssertIs(num, 3)) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order.go index e1110eec..432bb8f4 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order.go @@ -71,7 +71,7 @@ func ParseOrder(expressions ...string) []*Order { func OrderColumn(column string) OrderOption { return func(order *Order) { - order.column = column + order.column = strings.ReplaceAll(column, ExprSep, ExprDot) } } From 6d828e793968d982bd623ee9cae6e8dbc433e363 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Tue, 27 Oct 2020 19:32:56 +0800 Subject: [PATCH 08/31] move dir and add ut for ParseOrder --- client/orm/db_tables.go | 7 +- client/orm/orm.go | 4 +- client/orm/orm_conds.go | 4 +- client/orm/orm_queryset.go | 8 +- client/orm/orm_test.go | 20 ++-- .../orm/structs/clauses/{ => order}/order.go | 47 ++++---- .../orm/structs/clauses/order/order_test.go | 112 ++++++++++++++++++ client/orm/structs/clauses/order_test.go | 80 ------------- client/orm/structs/{clauses => }/const.go | 2 +- client/orm/types.go | 32 +++-- 10 files changed, 179 insertions(+), 137 deletions(-) rename client/orm/structs/clauses/{ => order}/order.go (54%) create mode 100644 client/orm/structs/clauses/order/order_test.go delete mode 100644 client/orm/structs/clauses/order_test.go rename client/orm/structs/{clauses => }/const.go (81%) diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 34fa0f07..94450f94 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -16,7 +16,8 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/structs/clauses" + "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/structs/clauses/order" "strings" "time" ) @@ -422,7 +423,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) { } // generate order sql. -func (t *dbTables) getOrderSQL(orders []*clauses.Order) (orderSQL string) { +func (t *dbTables) getOrderSQL(orders []*order.Order) (orderSQL string) { if len(orders) == 0 { return } @@ -432,7 +433,7 @@ func (t *dbTables) getOrderSQL(orders []*clauses.Order) (orderSQL string) { orderSqls := make([]string, 0, len(orders)) for _, order := range orders { column := order.GetColumn() - clause := strings.Split(column, clauses.ExprDot) + clause := strings.Split(column, structs.ExprDot) if order.IsRaw() { if len(clause) == 2 { diff --git a/client/orm/orm.go b/client/orm/orm.go index d1a66b88..27ae1fc2 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -58,7 +58,7 @@ import ( "database/sql" "errors" "fmt" - "github.com/astaxie/beego/client/orm/structs/clauses" + order2 "github.com/astaxie/beego/client/orm/structs/clauses/order" "os" "reflect" "time" @@ -352,7 +352,7 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s qs.relDepth = relDepth if len(order) > 0 { - qs.orders = clauses.ParseOrder(order) + qs.orders = order2.ParseOrder(order) } find := ind.FieldByIndex(fi.fieldIndex) diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index 7a798c6f..a2f6743c 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -16,13 +16,13 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/structs/clauses" + "github.com/astaxie/beego/client/orm/structs" "strings" ) // ExprSep define the expression separation const ( - ExprSep = clauses.ExprSep + ExprSep = structs.ExprSep ) type condValue struct { diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index e6493d8f..29b65b1a 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -18,7 +18,7 @@ import ( "context" "fmt" "github.com/astaxie/beego/client/orm/hints" - "github.com/astaxie/beego/client/orm/structs/clauses" + "github.com/astaxie/beego/client/orm/structs/clauses/order" ) type colValue struct { @@ -71,7 +71,7 @@ type querySet struct { limit int64 offset int64 groups []string - orders []*clauses.Order + orders []*order.Order distinct bool forUpdate bool useIndex int @@ -143,12 +143,12 @@ func (o querySet) OrderBy(expressions ...string) QuerySeter { if len(expressions) <= 0 { return &o } - o.orders = clauses.ParseOrder(expressions...) + o.orders = order.ParseOrder(expressions...) return &o } // add ORDER expression. -func (o querySet) OrderClauses(orders ...*clauses.Order) QuerySeter { +func (o querySet) OrderClauses(orders ...*order.Order) QuerySeter { if len(orders) <= 0 { return &o } diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index 8f057df1..e6041396 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -21,7 +21,7 @@ import ( "context" "database/sql" "fmt" - "github.com/astaxie/beego/client/orm/structs/clauses" + "github.com/astaxie/beego/client/orm/structs/clauses/order" "io/ioutil" "math" "os" @@ -1080,9 +1080,9 @@ func TestOrderBy(t *testing.T) { throwFail(t, AssertIs(num, 1)) num, err = qs.OrderClauses( - clauses.OrderClause( - clauses.OrderColumn(`profile__age`), - clauses.OrderSortDescending(), + order.Clause( + order.Column(`profile__age`), + order.SortDescending(), ), ).Filter("user_name", "astaxie").Count() throwFail(t, err) @@ -1090,9 +1090,9 @@ func TestOrderBy(t *testing.T) { if IsMysql { num, err = qs.OrderClauses( - clauses.OrderClause( - clauses.OrderColumn(`rand()`), - clauses.OrderRaw(), + order.Clause( + order.Column(`rand()`), + order.Raw(), ), ).Filter("user_name", "astaxie").Count() throwFail(t, err) @@ -1185,9 +1185,9 @@ func TestValues(t *testing.T) { } num, err = qs.OrderClauses( - clauses.OrderClause( - clauses.OrderColumn("Id"), - clauses.OrderSortAscending(), + order.Clause( + order.Column("Id"), + order.SortAscending(), ), ).Values(&maps) throwFail(t, err) diff --git a/client/orm/structs/clauses/order.go b/client/orm/structs/clauses/order/order.go similarity index 54% rename from client/orm/structs/clauses/order.go rename to client/orm/structs/clauses/order/order.go index 432bb8f4..c07202d5 100644 --- a/client/orm/structs/clauses/order.go +++ b/client/orm/structs/clauses/order/order.go @@ -1,16 +1,19 @@ -package clauses +package order -import "strings" +import ( + "github.com/astaxie/beego/client/orm/structs" + "strings" +) type Sort int8 const ( - SortNone Sort = 0 - SortAscending Sort = 1 - SortDescending Sort = 2 + None Sort = 0 + Ascending Sort = 1 + Descending Sort = 2 ) -type OrderOption func(order *Order) +type Option func(order *Order) type Order struct { column string @@ -18,7 +21,7 @@ type Order struct { isRaw bool } -func OrderClause(options ...OrderOption) *Order { +func Clause(options ...Option) *Order { o := &Order{} for _, option := range options { option(o) @@ -37,9 +40,9 @@ func (o *Order) GetSort() Sort { func (o *Order) SortString() string { switch o.GetSort() { - case SortAscending: + case Ascending: return "ASC" - case SortDescending: + case Descending: return "DESC" } @@ -53,10 +56,10 @@ func (o *Order) IsRaw() bool { func ParseOrder(expressions ...string) []*Order { var orders []*Order for _, expression := range expressions { - sort := SortAscending - column := strings.ReplaceAll(expression, ExprSep, ExprDot) + sort := Ascending + column := strings.ReplaceAll(expression, structs.ExprSep, structs.ExprDot) if column[0] == '-' { - sort = SortDescending + sort = Descending column = column[1:] } @@ -69,31 +72,31 @@ func ParseOrder(expressions ...string) []*Order { return orders } -func OrderColumn(column string) OrderOption { +func Column(column string) Option { return func(order *Order) { - order.column = strings.ReplaceAll(column, ExprSep, ExprDot) + order.column = strings.ReplaceAll(column, structs.ExprSep, structs.ExprDot) } } -func sort(sort Sort) OrderOption { +func sort(sort Sort) Option { return func(order *Order) { order.sort = sort } } -func OrderSortAscending() OrderOption { - return sort(SortAscending) +func SortAscending() Option { + return sort(Ascending) } -func OrderSortDescending() OrderOption { - return sort(SortDescending) +func SortDescending() Option { + return sort(Descending) } -func OrderSortNone() OrderOption { - return sort(SortNone) +func SortNone() Option { + return sort(None) } -func OrderRaw() OrderOption { +func Raw() Option { return func(order *Order) { order.isRaw = true } diff --git a/client/orm/structs/clauses/order/order_test.go b/client/orm/structs/clauses/order/order_test.go new file mode 100644 index 00000000..93072960 --- /dev/null +++ b/client/orm/structs/clauses/order/order_test.go @@ -0,0 +1,112 @@ +package order + +import ( + "testing" +) + +func TestOrderClause(t *testing.T) { + var ( + column = `a` + ) + + o := Clause( + Column(column), + ) + + if o.GetColumn() != column { + t.Error() + } +} + +func TestOrderSortAscending(t *testing.T) { + o := Clause( + SortAscending(), + ) + + if o.GetSort() != Ascending { + t.Error() + } +} + +func TestOrderSortDescending(t *testing.T) { + o := Clause( + SortDescending(), + ) + + if o.GetSort() != Descending { + t.Error() + } +} + +func TestOrderSortNone(t *testing.T) { + o1 := Clause( + SortNone(), + ) + + if o1.GetSort() != None { + t.Error() + } + + o2 := Clause() + + if o2.GetSort() != None { + t.Error() + } +} + +func TestOrderRaw(t *testing.T) { + o1 := Clause() + + if o1.IsRaw() { + t.Error() + } + + o2 := Clause( + Raw(), + ) + + if !o2.IsRaw() { + t.Error() + } +} + +func TestOrderColumn(t *testing.T) { + o1 := Clause( + Column(`aaa`), + ) + + if o1.GetColumn() != `aaa` { + t.Error() + } +} + +func TestParseOrder(t *testing.T) { + orders := ParseOrder( + `-user__status`, + `status`, + `user__status`, + ) + + t.Log(orders) + + if orders[0].GetSort() != Descending { + t.Error() + } + + if orders[0].GetColumn() != `user.status` { + t.Error() + } + + if orders[1].GetColumn() != `status` { + t.Error() + } + + if orders[1].GetSort() != Ascending { + t.Error() + } + + if orders[2].GetColumn() != `user.status` { + t.Error() + } + +} diff --git a/client/orm/structs/clauses/order_test.go b/client/orm/structs/clauses/order_test.go deleted file mode 100644 index dbb37a0a..00000000 --- a/client/orm/structs/clauses/order_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package clauses - -import "testing" - -func TestOrderClause(t *testing.T) { - var ( - column = `a` - ) - - o := OrderClause( - OrderColumn(column), - ) - - if o.GetColumn() != column { - t.Error() - } -} - -func TestOrderSortAscending(t *testing.T) { - o := OrderClause( - OrderSortAscending(), - ) - - if o.GetSort() != SortAscending { - t.Error() - } -} - -func TestOrderSortDescending(t *testing.T) { - o := OrderClause( - OrderSortDescending(), - ) - - if o.GetSort() != SortDescending { - t.Error() - } -} - -func TestOrderSortNone(t *testing.T) { - o1 := OrderClause( - OrderSortNone(), - ) - - if o1.GetSort() != SortNone { - t.Error() - } - - o2 := OrderClause() - - if o2.GetSort() != SortNone { - t.Error() - } -} - -func TestOrderRaw(t *testing.T) { - o1 := OrderClause() - - if o1.IsRaw() { - t.Error() - } - - o2 := OrderClause( - OrderRaw(), - ) - - if !o2.IsRaw() { - t.Error() - } -} - -func TestOrderColumn(t *testing.T) { - o1 := OrderClause( - OrderColumn(`aaa`), - ) - - if o1.GetColumn() != `aaa` { - t.Error() - } -} - diff --git a/client/orm/structs/clauses/const.go b/client/orm/structs/const.go similarity index 81% rename from client/orm/structs/clauses/const.go rename to client/orm/structs/const.go index 747d3fd7..42a1845a 100644 --- a/client/orm/structs/clauses/const.go +++ b/client/orm/structs/const.go @@ -1,4 +1,4 @@ -package clauses +package structs const ( ExprSep = "__" diff --git a/client/orm/types.go b/client/orm/types.go index 14a34025..d39aa75c 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -17,7 +17,7 @@ package orm import ( "context" "database/sql" - "github.com/astaxie/beego/client/orm/structs/clauses" + "github.com/astaxie/beego/client/orm/structs/clauses/order" "reflect" "time" @@ -292,20 +292,26 @@ type QuerySeter interface { OrderBy(exprs ...string) QuerySeter // add ORDER expression by order clauses // for example: - // OrderClauses(clauses.OrderClause( - // clauses.OrderColumn(`status`), - // clauses.OrderSortAscending(),//default None + // OrderClauses( + // order.Clause( + // order.Column("Id"), + // order.SortAscending(), + // ), + // order.Clause( + // order.Column("status"), + // order.SortDescending(), + // ), + // ) + // OrderClauses(order.Clause( + // order.Column(`user__status`), + // order.SortDescending(),//default None // )) - // OrderClauses(clauses.OrderClause( - // clauses.OrderColumn(`user__status`), - // clauses.OrderSortDescending(),//default None + // OrderClauses(order.Clause( + // order.Column(`random()`), + // order.SortNone(),//default None + // order.Raw(),//default false.if true, do not check field is valid or not // )) - // OrderClauses(clauses.OrderClause( - // clauses.OrderColumn(`random()`), - // clauses.OrderSortNone(),//default None - // clauses.OrderRaw(),//default false.if true, do not check field is valid or not - // )) - OrderClauses(orders ...*clauses.Order) QuerySeter + OrderClauses(orders ...*order.Order) QuerySeter // add FORCE INDEX expression. // for example: // qs.ForceIndex(`idx_name1`,`idx_name2`) From d147f4a0184abaf759b7c1f30eb7242b03b439df Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Tue, 27 Oct 2020 19:35:35 +0800 Subject: [PATCH 09/31] format comment --- client/orm/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/orm/types.go b/client/orm/types.go index d39aa75c..6630e14f 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -302,11 +302,11 @@ type QuerySeter interface { // order.SortDescending(), // ), // ) - // OrderClauses(order.Clause( + // OrderClauses(order.Clause( // order.Column(`user__status`), // order.SortDescending(),//default None // )) - // OrderClauses(order.Clause( + // OrderClauses(order.Clause( // order.Column(`random()`), // order.SortNone(),//default None // order.Raw(),//default false.if true, do not check field is valid or not From 759982b3b856f322a0d600487a627dac81bd09c4 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Tue, 27 Oct 2020 20:01:53 +0800 Subject: [PATCH 10/31] add more UT --- .../orm/structs/clauses/order/order_test.go | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/client/orm/structs/clauses/order/order_test.go b/client/orm/structs/clauses/order/order_test.go index 93072960..0e9356f0 100644 --- a/client/orm/structs/clauses/order/order_test.go +++ b/client/orm/structs/clauses/order/order_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func TestOrderClause(t *testing.T) { +func TestClause(t *testing.T) { var ( column = `a` ) @@ -18,7 +18,7 @@ func TestOrderClause(t *testing.T) { } } -func TestOrderSortAscending(t *testing.T) { +func TestSortAscending(t *testing.T) { o := Clause( SortAscending(), ) @@ -28,7 +28,7 @@ func TestOrderSortAscending(t *testing.T) { } } -func TestOrderSortDescending(t *testing.T) { +func TestSortDescending(t *testing.T) { o := Clause( SortDescending(), ) @@ -38,7 +38,7 @@ func TestOrderSortDescending(t *testing.T) { } } -func TestOrderSortNone(t *testing.T) { +func TestSortNone(t *testing.T) { o1 := Clause( SortNone(), ) @@ -54,7 +54,7 @@ func TestOrderSortNone(t *testing.T) { } } -func TestOrderRaw(t *testing.T) { +func TestRaw(t *testing.T) { o1 := Clause() if o1.IsRaw() { @@ -70,7 +70,7 @@ func TestOrderRaw(t *testing.T) { } } -func TestOrderColumn(t *testing.T) { +func TestColumn(t *testing.T) { o1 := Clause( Column(`aaa`), ) @@ -110,3 +110,35 @@ func TestParseOrder(t *testing.T) { } } + +func TestOrder_GetColumn(t *testing.T) { + o := Clause( + Column(`user__id`), + ) + if o.GetColumn() != `user.id` { + t.Error() + } +} + +func TestOrder_GetSort(t *testing.T) { + o := Clause( + SortDescending(), + ) + if o.GetSort() != Descending { + t.Error() + } +} + +func TestOrder_IsRaw(t *testing.T) { + o1 := Clause() + if o1.IsRaw() { + t.Error() + } + + o2 := Clause( + Raw(), + ) + if !o2.IsRaw() { + t.Error() + } +} From 508105d32ac0b4e34d1094535e577a8d9f90ee34 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Thu, 29 Oct 2020 18:57:16 +0800 Subject: [PATCH 11/31] fix UT:concurrent map iteration and map write --- task/task.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/task/task.go b/task/task.go index 8f25a0f3..00cbbfa7 100644 --- a/task/task.go +++ b/task/task.go @@ -452,9 +452,11 @@ func (m *taskManager) StartTask() { func (m *taskManager) run() { now := time.Now().Local() + m.taskLock.Lock() for _, t := range m.adminTaskList { t.SetNext(nil, now) } + m.taskLock.Unlock() for { // we only use RLock here because NewMapSorter copy the reference, do not change any thing From f8fb50999bc7305256d6c1844313169aab53a9c8 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Thu, 29 Oct 2020 19:05:32 +0800 Subject: [PATCH 12/31] move dir --- client/orm/{structs => clauses}/const.go | 2 +- .../order => clauses/order_clause}/order.go | 8 +++---- .../order_clause}/order_test.go | 2 +- client/orm/db_tables.go | 7 +++--- client/orm/orm.go | 4 ++-- client/orm/orm_conds.go | 4 ++-- client/orm/orm_queryset.go | 8 +++---- client/orm/orm_test.go | 20 ++++++++--------- client/orm/types.go | 22 +++++++++---------- 9 files changed, 38 insertions(+), 39 deletions(-) rename client/orm/{structs => clauses}/const.go (81%) rename client/orm/{structs/clauses/order => clauses/order_clause}/order.go (85%) rename client/orm/{structs/clauses/order => clauses/order_clause}/order_test.go (98%) diff --git a/client/orm/structs/const.go b/client/orm/clauses/const.go similarity index 81% rename from client/orm/structs/const.go rename to client/orm/clauses/const.go index 42a1845a..747d3fd7 100644 --- a/client/orm/structs/const.go +++ b/client/orm/clauses/const.go @@ -1,4 +1,4 @@ -package structs +package clauses const ( ExprSep = "__" diff --git a/client/orm/structs/clauses/order/order.go b/client/orm/clauses/order_clause/order.go similarity index 85% rename from client/orm/structs/clauses/order/order.go rename to client/orm/clauses/order_clause/order.go index c07202d5..510c5505 100644 --- a/client/orm/structs/clauses/order/order.go +++ b/client/orm/clauses/order_clause/order.go @@ -1,7 +1,7 @@ -package order +package order_clause import ( - "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/clauses" "strings" ) @@ -57,7 +57,7 @@ func ParseOrder(expressions ...string) []*Order { var orders []*Order for _, expression := range expressions { sort := Ascending - column := strings.ReplaceAll(expression, structs.ExprSep, structs.ExprDot) + column := strings.ReplaceAll(expression, clauses.ExprSep, clauses.ExprDot) if column[0] == '-' { sort = Descending column = column[1:] @@ -74,7 +74,7 @@ func ParseOrder(expressions ...string) []*Order { func Column(column string) Option { return func(order *Order) { - order.column = strings.ReplaceAll(column, structs.ExprSep, structs.ExprDot) + order.column = strings.ReplaceAll(column, clauses.ExprSep, clauses.ExprDot) } } diff --git a/client/orm/structs/clauses/order/order_test.go b/client/orm/clauses/order_clause/order_test.go similarity index 98% rename from client/orm/structs/clauses/order/order_test.go rename to client/orm/clauses/order_clause/order_test.go index 0e9356f0..172e7492 100644 --- a/client/orm/structs/clauses/order/order_test.go +++ b/client/orm/clauses/order_clause/order_test.go @@ -1,4 +1,4 @@ -package order +package order_clause import ( "testing" diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 94450f94..76a14fd0 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -16,8 +16,7 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/structs" - "github.com/astaxie/beego/client/orm/structs/clauses/order" + "github.com/astaxie/beego/client/orm/clauses" "strings" "time" ) @@ -423,7 +422,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) { } // generate order sql. -func (t *dbTables) getOrderSQL(orders []*order.Order) (orderSQL string) { +func (t *dbTables) getOrderSQL(orders []*order_clause.Order) (orderSQL string) { if len(orders) == 0 { return } @@ -433,7 +432,7 @@ func (t *dbTables) getOrderSQL(orders []*order.Order) (orderSQL string) { orderSqls := make([]string, 0, len(orders)) for _, order := range orders { column := order.GetColumn() - clause := strings.Split(column, structs.ExprDot) + clause := strings.Split(column, clauses.ExprDot) if order.IsRaw() { if len(clause) == 2 { diff --git a/client/orm/orm.go b/client/orm/orm.go index 27ae1fc2..a228c626 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -58,7 +58,7 @@ import ( "database/sql" "errors" "fmt" - order2 "github.com/astaxie/beego/client/orm/structs/clauses/order" + "github.com/astaxie/beego/client/orm/clauses/order_clause" "os" "reflect" "time" @@ -352,7 +352,7 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s qs.relDepth = relDepth if len(order) > 0 { - qs.orders = order2.ParseOrder(order) + qs.orders = order_clause.ParseOrder(order) } find := ind.FieldByIndex(fi.fieldIndex) diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index a2f6743c..fbf62c5a 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -16,13 +16,13 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/structs" + "github.com/astaxie/beego/client/orm/clauses" "strings" ) // ExprSep define the expression separation const ( - ExprSep = structs.ExprSep + ExprSep = clauses.ExprSep ) type condValue struct { diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 29b65b1a..45900487 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -18,7 +18,7 @@ import ( "context" "fmt" "github.com/astaxie/beego/client/orm/hints" - "github.com/astaxie/beego/client/orm/structs/clauses/order" + "github.com/astaxie/beego/client/orm/clauses/order_clause" ) type colValue struct { @@ -71,7 +71,7 @@ type querySet struct { limit int64 offset int64 groups []string - orders []*order.Order + orders []*order_clause.Order distinct bool forUpdate bool useIndex int @@ -143,12 +143,12 @@ func (o querySet) OrderBy(expressions ...string) QuerySeter { if len(expressions) <= 0 { return &o } - o.orders = order.ParseOrder(expressions...) + o.orders = order_clause.ParseOrder(expressions...) return &o } // add ORDER expression. -func (o querySet) OrderClauses(orders ...*order.Order) QuerySeter { +func (o querySet) OrderClauses(orders ...*order_clause.Order) QuerySeter { if len(orders) <= 0 { return &o } diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index e6041396..2f3f9d55 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -21,7 +21,7 @@ import ( "context" "database/sql" "fmt" - "github.com/astaxie/beego/client/orm/structs/clauses/order" + "github.com/astaxie/beego/client/orm/clauses/order_clause" "io/ioutil" "math" "os" @@ -1080,9 +1080,9 @@ func TestOrderBy(t *testing.T) { throwFail(t, AssertIs(num, 1)) num, err = qs.OrderClauses( - order.Clause( - order.Column(`profile__age`), - order.SortDescending(), + order_clause.Clause( + order_clause.Column(`profile__age`), + order_clause.SortDescending(), ), ).Filter("user_name", "astaxie").Count() throwFail(t, err) @@ -1090,9 +1090,9 @@ func TestOrderBy(t *testing.T) { if IsMysql { num, err = qs.OrderClauses( - order.Clause( - order.Column(`rand()`), - order.Raw(), + order_clause.Clause( + order_clause.Column(`rand()`), + order_clause.Raw(), ), ).Filter("user_name", "astaxie").Count() throwFail(t, err) @@ -1185,9 +1185,9 @@ func TestValues(t *testing.T) { } num, err = qs.OrderClauses( - order.Clause( - order.Column("Id"), - order.SortAscending(), + order_clause.Clause( + order_clause.Column("Id"), + order_clause.SortAscending(), ), ).Values(&maps) throwFail(t, err) diff --git a/client/orm/types.go b/client/orm/types.go index 6630e14f..5da40830 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -17,7 +17,7 @@ package orm import ( "context" "database/sql" - "github.com/astaxie/beego/client/orm/structs/clauses/order" + "github.com/astaxie/beego/client/orm/clauses/order_clause" "reflect" "time" @@ -293,25 +293,25 @@ type QuerySeter interface { // add ORDER expression by order clauses // for example: // OrderClauses( - // order.Clause( + // order_clause.Clause( // order.Column("Id"), // order.SortAscending(), // ), - // order.Clause( + // order_clause.Clause( // order.Column("status"), // order.SortDescending(), // ), // ) - // OrderClauses(order.Clause( - // order.Column(`user__status`), - // order.SortDescending(),//default None + // OrderClauses(order_clause.Clause( + // order_clause.Column(`user__status`), + // order_clause.SortDescending(),//default None // )) - // OrderClauses(order.Clause( - // order.Column(`random()`), - // order.SortNone(),//default None - // order.Raw(),//default false.if true, do not check field is valid or not + // OrderClauses(order_clause.Clause( + // order_clause.Column(`random()`), + // order_clause.SortNone(),//default None + // order_clause.Raw(),//default false.if true, do not check field is valid or not // )) - OrderClauses(orders ...*order.Order) QuerySeter + OrderClauses(orders ...*order_clause.Order) QuerySeter // add FORCE INDEX expression. // for example: // qs.ForceIndex(`idx_name1`,`idx_name2`) From f864e585e1b82815816e9acfbdfddad8dc9986b9 Mon Sep 17 00:00:00 2001 From: jianzhiyao Date: Thu, 29 Oct 2020 19:07:42 +0800 Subject: [PATCH 13/31] fix import --- client/orm/db_tables.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 76a14fd0..82b8ab7e 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -17,6 +17,7 @@ package orm import ( "fmt" "github.com/astaxie/beego/client/orm/clauses" + "github.com/astaxie/beego/client/orm/clauses/order_clause" "strings" "time" ) From 41b1833898cd9843355f057599392a56c7e54ada Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 2 Jan 2021 21:55:12 +0800 Subject: [PATCH 14/31] make session easier to be configured --- server/web/session/redis/sess_redis_test.go | 21 +-- .../sess_redis_sentinel_test.go | 18 +-- server/web/session/session.go | 19 --- server/web/session/session_config.go | 137 ++++++++++++++++++ server/web/session/session_provider_type.go | 16 ++ 5 files changed, 173 insertions(+), 38 deletions(-) create mode 100644 server/web/session/session_config.go create mode 100644 server/web/session/session_provider_type.go diff --git a/server/web/session/redis/sess_redis_test.go b/server/web/session/redis/sess_redis_test.go index fe5c363b..2b15eef1 100644 --- a/server/web/session/redis/sess_redis_test.go +++ b/server/web/session/redis/sess_redis_test.go @@ -15,21 +15,22 @@ import ( ) func TestRedis(t *testing.T) { - sessionConfig := &session.ManagerConfig{ - CookieName: "gosessionid", - EnableSetCookie: true, - Gclifetime: 3600, - Maxlifetime: 3600, - Secure: false, - CookieLifeTime: 3600, - } - redisAddr := os.Getenv("REDIS_ADDR") if redisAddr == "" { redisAddr = "127.0.0.1:6379" } + redisConfig := fmt.Sprintf("%s,100,,0,30", redisAddr) + + sessionConfig := session.NewManagerConfig( + session.CfgCookieName(`gosessionid`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + session.CfgProviderConfig(redisConfig), + ) - sessionConfig.ProviderConfig = fmt.Sprintf("%s,100,,0,30", redisAddr) globalSession, err := session.NewManager("redis", sessionConfig) if err != nil { t.Fatal("could not create manager:", err) diff --git a/server/web/session/redis_sentinel/sess_redis_sentinel_test.go b/server/web/session/redis_sentinel/sess_redis_sentinel_test.go index 0a8030ce..489e8998 100644 --- a/server/web/session/redis_sentinel/sess_redis_sentinel_test.go +++ b/server/web/session/redis_sentinel/sess_redis_sentinel_test.go @@ -13,15 +13,15 @@ import ( ) func TestRedisSentinel(t *testing.T) { - sessionConfig := &session.ManagerConfig{ - CookieName: "gosessionid", - EnableSetCookie: true, - Gclifetime: 3600, - Maxlifetime: 3600, - Secure: false, - CookieLifeTime: 3600, - ProviderConfig: "127.0.0.1:6379,100,,0,master", - } + sessionConfig := session.NewManagerConfig( + session.CfgCookieName(`gosessionid`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + session.CfgProviderConfig("127.0.0.1:6379,100,,0,master"), + ) globalSessions, e := session.NewManager("redis_sentinel", sessionConfig) if e != nil { t.Log(e) diff --git a/server/web/session/session.go b/server/web/session/session.go index 6b53ec29..ca0407e8 100644 --- a/server/web/session/session.go +++ b/server/web/session/session.go @@ -91,25 +91,6 @@ func GetProvider(name string) (Provider, error) { return provider, nil } -// ManagerConfig define the session config -type ManagerConfig struct { - CookieName string `json:"cookieName"` - EnableSetCookie bool `json:"enableSetCookie,omitempty"` - Gclifetime int64 `json:"gclifetime"` - Maxlifetime int64 `json:"maxLifetime"` - DisableHTTPOnly bool `json:"disableHTTPOnly"` - Secure bool `json:"secure"` - CookieLifeTime int `json:"cookieLifeTime"` - ProviderConfig string `json:"providerConfig"` - Domain string `json:"domain"` - SessionIDLength int64 `json:"sessionIDLength"` - EnableSidInHTTPHeader bool `json:"EnableSidInHTTPHeader"` - SessionNameInHTTPHeader string `json:"SessionNameInHTTPHeader"` - EnableSidInURLQuery bool `json:"EnableSidInURLQuery"` - SessionIDPrefix string `json:"sessionIDPrefix"` - CookieSameSite http.SameSite `json:"cookieSameSite"` -} - // Manager contains Provider and its configuration. type Manager struct { provider Provider diff --git a/server/web/session/session_config.go b/server/web/session/session_config.go new file mode 100644 index 00000000..a1e24ae3 --- /dev/null +++ b/server/web/session/session_config.go @@ -0,0 +1,137 @@ +package session + +import "net/http" + +// ManagerConfig define the session config +type ManagerConfig struct { + CookieName string `json:"cookieName"` + EnableSetCookie bool `json:"enableSetCookie,omitempty"` + Gclifetime int64 `json:"gclifetime"` + Maxlifetime int64 `json:"maxLifetime"` + DisableHTTPOnly bool `json:"disableHTTPOnly"` + Secure bool `json:"secure"` + CookieLifeTime int `json:"cookieLifeTime"` + ProviderConfig string `json:"providerConfig"` + Domain string `json:"domain"` + SessionIDLength int64 `json:"sessionIDLength"` + EnableSidInHTTPHeader bool `json:"EnableSidInHTTPHeader"` + SessionNameInHTTPHeader string `json:"SessionNameInHTTPHeader"` + EnableSidInURLQuery bool `json:"EnableSidInURLQuery"` + SessionIDPrefix string `json:"sessionIDPrefix"` + CookieSameSite http.SameSite `json:"cookieSameSite"` +} + +type ManagerConfigOpt func(config *ManagerConfig) + +func NewManagerConfig(opts ...ManagerConfigOpt) *ManagerConfig { + config := &ManagerConfig{} + for _, opt := range opts { + opt(config) + } + return config +} + +// CfgCookieName set key of session id +func CfgCookieName(cookieName string) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.CookieName = cookieName + } +} + +// CfgCookieName set len of session id +func CfgSessionIdLength(len int64) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.SessionIDLength = len + } +} + +// CfgSessionIdPrefix set prefix of session id +func CfgSessionIdPrefix(prefix string) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.SessionIDPrefix = prefix + } +} + +//CfgSetCookie whether set `Set-Cookie` header in HTTP response +func CfgSetCookie(enable bool) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.EnableSetCookie = enable + } +} + +//CfgGcLifeTime set session gc lift time +func CfgGcLifeTime(lifeTime int64) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.Gclifetime = lifeTime + } +} + +//CfgMaxLifeTime set session lift time +func CfgMaxLifeTime(lifeTime int64) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.Maxlifetime = lifeTime + } +} + +//CfgGcLifeTime set session lift time +func CfgCookieLifeTime(lifeTime int) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.CookieLifeTime = lifeTime + } +} + +//CfgProviderConfig configure session provider +func CfgProviderConfig(providerConfig string) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.ProviderConfig = providerConfig + } +} + +//CfgDomain set cookie domain +func CfgDomain(domain string) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.Domain = domain + } +} + +//CfgSessionIdInHTTPHeader enable session id in http header +func CfgSessionIdInHTTPHeader(enable bool) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.EnableSidInHTTPHeader = enable + } +} + +//CfgSetSessionNameInHTTPHeader set key of session id in http header +func CfgSetSessionNameInHTTPHeader(name string) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.SessionNameInHTTPHeader = name + } +} + +//EnableSidInURLQuery enable session id in query string +func CfgEnableSidInURLQuery(enable bool) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.EnableSidInURLQuery = enable + } +} + +//DisableHTTPOnly set HTTPOnly for http.Cookie +func CfgHTTPOnly(HTTPOnly bool) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.DisableHTTPOnly = !HTTPOnly + } +} + +//CfgSecure set Secure for http.Cookie +func CfgSecure(Enable bool) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.Secure = Enable + } +} + +//CfgSameSite set http.SameSite +func CfgSameSite(sameSite http.SameSite) ManagerConfigOpt { + return func(config *ManagerConfig) { + config.CookieSameSite = sameSite + } +} diff --git a/server/web/session/session_provider_type.go b/server/web/session/session_provider_type.go new file mode 100644 index 00000000..c14a3ecc --- /dev/null +++ b/server/web/session/session_provider_type.go @@ -0,0 +1,16 @@ +package session + +const ( + ProviderCookie = `cookie` + ProviderFile = `file` + ProviderMemory = `memory` + ProviderCouchbase = `couchbase` + ProviderLedis = `ledis` + ProviderMemcache = `memcache` + ProviderMysql = `mysql` + ProviderPostgresql = `postgresql` + ProviderRedis = `redis` + ProviderRedisCluster = `redis_cluster` + ProviderRedisSentinel = `redis_sentinel` + ProviderSsdb = `ssdb` +) From a4f8fbd5a14e97a3e8ad5f2ec9e87a80c6f7dea9 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 3 Jan 2021 00:33:44 +0800 Subject: [PATCH 15/31] add session filter & UT --- go.mod | 2 +- server/web/filter/session/filter.go | 65 ++++++++++++ server/web/filter/session/filter_test.go | 112 ++++++++++++++++++++ server/web/session/session_provider_type.go | 26 ++--- 4 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 server/web/filter/session/filter.go create mode 100644 server/web/filter/session/filter_test.go diff --git a/go.mod b/go.mod index 89baa406..ce67b7d2 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/gomodule/redigo v2.0.0+incompatible github.com/google/go-cmp v0.5.0 // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/google/uuid v1.1.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/hashicorp/golang-lru v0.5.4 github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6 diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go new file mode 100644 index 00000000..b37a9f51 --- /dev/null +++ b/server/web/filter/session/filter.go @@ -0,0 +1,65 @@ +package session + +import ( + "context" + "errors" + "fmt" + "github.com/beego/beego/v2/core/logs" + "github.com/beego/beego/v2/server/web" + webContext "github.com/beego/beego/v2/server/web/context" + "github.com/beego/beego/v2/server/web/session" + "github.com/google/uuid" + "sync" +) + +var ( + sessionKey string + sessionKeyOnce sync.Once +) + +func getSessionKey() string { + + sessionKeyOnce.Do(func() { + //generate an unique session store key + sessionKey = fmt.Sprintf(`sess_store:%d`, uuid.New().ID()) + }) + + return sessionKey +} + +func Session(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { + sessionConfig := session.NewManagerConfig(options...) + sessionManager, _ := session.NewManager(string(providerType), sessionConfig) + go sessionManager.GC() + + return func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + + if sess, err := sessionManager.SessionStart(ctx.ResponseWriter, ctx.Request); err != nil { + logs.Warning(`init session error:%s`, err.Error()) + } else { + //release session at the end of request + defer sess.SessionRelease(context.Background(), ctx.ResponseWriter) + ctx.Input.SetData(getSessionKey(), sess) + } + + next(ctx) + + } + } +} + +func GetStore(ctx *webContext.Context) (store session.Store, err error) { + if ctx == nil { + err = errors.New(`ctx is nil`) + return + } + + if s, ok := ctx.Input.GetData(getSessionKey()).(session.Store); ok { + store = s + return + } else { + err = errors.New(`can not get a valid session store`) + return + } +} diff --git a/server/web/filter/session/filter_test.go b/server/web/filter/session/filter_test.go new file mode 100644 index 00000000..7b24f6ad --- /dev/null +++ b/server/web/filter/session/filter_test.go @@ -0,0 +1,112 @@ +package session + +import ( + "context" + "github.com/beego/beego/v2/server/web" + webContext "github.com/beego/beego/v2/server/web/context" + "github.com/beego/beego/v2/server/web/session" + "net/http" + "net/http/httptest" + "testing" +) + +func testRequest(t *testing.T, handler *web.ControllerRegister, path string, method string, code int) { + r, _ := http.NewRequest(method, path, nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + if w.Code != code { + t.Errorf("%s, %s: %d, supposed to be %d", path, method, w.Code, code) + } +} + +func TestSession(t *testing.T) { + handler := web.NewControllerRegister() + handler.InsertFilterChain( + "*", + Session( + session.ProviderMemory, + session.CfgCookieName(`go_session_id`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + if store := ctx.Input.GetData(getSessionKey()); store == nil { + t.Error(`store should not be nil`) + } + next(ctx) + } + }, + ) + handler.Any("*", func(ctx *webContext.Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} + +func TestGetStore(t *testing.T) { + handler := web.NewControllerRegister() + + handler.InsertFilterChain( + "*", + Session( + session.ProviderMemory, + session.CfgCookieName(`go_session_id`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + var ( + checkKey = `asodiuasdk1j)AS(87` + checkValue = `ASsd-09812-3` + + store session.Store + err error + + c = context.Background() + ) + + if store, err = GetStore(ctx); err == nil { + if store == nil { + t.Error(`store should not be nil`) + } else { + _ = store.Set(c, checkKey, checkValue) + } + } else { + t.Error(err) + } + + next(ctx) + + if store != nil { + if v := store.Get(c, checkKey); v != checkValue { + t.Error(v, `is not equals to`, checkValue) + } + }else{ + t.Error(`store should not be nil`) + } + + } + }, + ) + handler.Any("*", func(ctx *webContext.Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} diff --git a/server/web/session/session_provider_type.go b/server/web/session/session_provider_type.go index c14a3ecc..78dc116d 100644 --- a/server/web/session/session_provider_type.go +++ b/server/web/session/session_provider_type.go @@ -1,16 +1,18 @@ package session +type ProviderType string + const ( - ProviderCookie = `cookie` - ProviderFile = `file` - ProviderMemory = `memory` - ProviderCouchbase = `couchbase` - ProviderLedis = `ledis` - ProviderMemcache = `memcache` - ProviderMysql = `mysql` - ProviderPostgresql = `postgresql` - ProviderRedis = `redis` - ProviderRedisCluster = `redis_cluster` - ProviderRedisSentinel = `redis_sentinel` - ProviderSsdb = `ssdb` + ProviderCookie ProviderType = `cookie` + ProviderFile ProviderType = `file` + ProviderMemory ProviderType = `memory` + ProviderCouchbase ProviderType = `couchbase` + ProviderLedis ProviderType = `ledis` + ProviderMemcache ProviderType = `memcache` + ProviderMysql ProviderType = `mysql` + ProviderPostgresql ProviderType = `postgresql` + ProviderRedis ProviderType = `redis` + ProviderRedisCluster ProviderType = `redis_cluster` + ProviderRedisSentinel ProviderType = `redis_sentinel` + ProviderSsdb ProviderType = `ssdb` ) From 9105402f8ce1ad21523bc913d9dbd48bdfd7230c Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Fri, 8 Jan 2021 20:52:36 +0800 Subject: [PATCH 16/31] reverse filter chain sort and add test to ensure the FIFO --- client/httplib/httplib_test.go | 22 +++++++++++++++++++ server/web/filter_chain_test.go | 38 ++++++++++++++++++++++++++++++++- server/web/router.go | 32 ++++++++++++++++++++++----- server/web/server.go | 2 ++ 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/client/httplib/httplib_test.go b/client/httplib/httplib_test.go index 1763b1b5..b8cd1112 100644 --- a/client/httplib/httplib_test.go +++ b/client/httplib/httplib_test.go @@ -301,6 +301,28 @@ func TestAddFilter(t *testing.T) { assert.Equal(t, 1, len(req.setting.FilterChains)-len(r.setting.FilterChains)) } +func TestFilterChainOrder(t *testing.T) { + req := Get("http://beego.me") + req.AddFilters(func(next Filter) Filter { + return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { + return NewHttpResponseWithJsonBody("first"), nil + } + }) + + + req.AddFilters(func(next Filter) Filter { + return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { + return NewHttpResponseWithJsonBody("second"), nil + } + }) + + resp, err := req.DoRequestWithCtx(context.Background()) + assert.Nil(t, err) + data := make([]byte, 5) + _, _ = resp.Body.Read(data) + assert.Equal(t, "first", string(data)) +} + func TestHead(t *testing.T) { req := Head("http://beego.me") assert.NotNil(t, req) diff --git a/server/web/filter_chain_test.go b/server/web/filter_chain_test.go index 2a428b78..5dd38fc5 100644 --- a/server/web/filter_chain_test.go +++ b/server/web/filter_chain_test.go @@ -15,9 +15,12 @@ package web import ( + "fmt" "net/http" "net/http/httptest" + "strconv" "testing" + "time" "github.com/stretchr/testify/assert" @@ -36,13 +39,46 @@ func TestControllerRegister_InsertFilterChain(t *testing.T) { ns := NewNamespace("/chain") ns.Get("/*", func(ctx *context.Context) { - ctx.Output.Body([]byte("hello")) + _ = ctx.Output.Body([]byte("hello")) }) r, _ := http.NewRequest("GET", "/chain/user", nil) w := httptest.NewRecorder() + BeeApp.Handlers.Init() BeeApp.Handlers.ServeHTTP(w, r) assert.Equal(t, "filter-chain", w.Header().Get("filter")) } + +func TestControllerRegister_InsertFilterChain_Order(t *testing.T) { + InsertFilterChain("/abc", func(next FilterFunc) FilterFunc { + return func(ctx *context.Context) { + ctx.Output.Header("first", fmt.Sprintf("%d", time.Now().UnixNano())) + time.Sleep(time.Millisecond * 10) + next(ctx) + } + }) + + + InsertFilterChain("/abc", func(next FilterFunc) FilterFunc { + return func(ctx *context.Context) { + ctx.Output.Header("second", fmt.Sprintf("%d", time.Now().UnixNano())) + time.Sleep(time.Millisecond * 10) + next(ctx) + } + }) + + r, _ := http.NewRequest("GET", "/abc", nil) + w := httptest.NewRecorder() + + BeeApp.Handlers.Init() + BeeApp.Handlers.ServeHTTP(w, r) + first := w.Header().Get("first") + second := w.Header().Get("second") + + ft, _ := strconv.ParseInt(first, 10, 64) + st, _ := strconv.ParseInt(second, 10, 64) + + assert.True(t, st > ft) +} diff --git a/server/web/router.go b/server/web/router.go index 613c4172..9ba078bf 100644 --- a/server/web/router.go +++ b/server/web/router.go @@ -139,6 +139,12 @@ func WithRouterSessionOn(sessionOn bool) ControllerOption { } } +type filterChainConfig struct { + pattern string + chain FilterChain + opts []FilterOpt +} + // ControllerRegister containers registered router rules, controller handlers and filters. type ControllerRegister struct { routers map[string]*Tree @@ -151,6 +157,9 @@ type ControllerRegister struct { // the filter created by FilterChain chainRoot *FilterRouter + // keep registered chain and build it when serve http + filterChains []filterChainConfig + cfg *Config } @@ -171,11 +180,23 @@ func NewControllerRegisterWithCfg(cfg *Config) *ControllerRegister { }, }, cfg: cfg, + filterChains: make([]filterChainConfig, 0, 4), } res.chainRoot = newFilterRouter("/*", res.serveHttp, WithCaseSensitive(false)) return res } +// Init will be executed when HttpServer start running +func (p *ControllerRegister) Init() { + for i := len(p.filterChains) - 1; i >= 0 ; i -- { + fc := p.filterChains[i] + root := p.chainRoot + filterFunc := fc.chain(root.filterFunc) + p.chainRoot = newFilterRouter(fc.pattern, filterFunc, fc.opts...) + p.chainRoot.next = root + } +} + // Add controller handler and pattern rules to ControllerRegister. // usage: // default methods is the same name as method @@ -513,12 +534,13 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter // } // } func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, opts ...FilterOpt) { - root := p.chainRoot - filterFunc := chain(root.filterFunc) - opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive)) - p.chainRoot = newFilterRouter(pattern, filterFunc, opts...) - p.chainRoot.next = root + opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive)) + p.filterChains = append(p.filterChains, filterChainConfig{ + pattern: pattern, + chain: chain, + opts: opts, + }) } // add Filter into diff --git a/server/web/server.go b/server/web/server.go index 6c4eaf9e..548b906b 100644 --- a/server/web/server.go +++ b/server/web/server.go @@ -84,7 +84,9 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) { initBeforeHTTPRun() + // init... app.initAddr(addr) + app.Handlers.Init() addr = app.Cfg.Listen.HTTPAddr From 833d7349216f33a1ca7503913562a65b20372f34 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 10:13:44 +0800 Subject: [PATCH 17/31] add UT and ManagerConfig.Opts(opts ...ManagerConfigOpt) --- server/web/session/session_config.go | 6 + server/web/session/session_config_test.go | 222 ++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 server/web/session/session_config_test.go diff --git a/server/web/session/session_config.go b/server/web/session/session_config.go index a1e24ae3..e42247db 100644 --- a/server/web/session/session_config.go +++ b/server/web/session/session_config.go @@ -21,6 +21,12 @@ type ManagerConfig struct { CookieSameSite http.SameSite `json:"cookieSameSite"` } +func (c *ManagerConfig) Opts(opts ...ManagerConfigOpt) { + for _, opt := range opts { + opt(c) + } +} + type ManagerConfigOpt func(config *ManagerConfig) func NewManagerConfig(opts ...ManagerConfigOpt) *ManagerConfig { diff --git a/server/web/session/session_config_test.go b/server/web/session/session_config_test.go new file mode 100644 index 00000000..a596c5c6 --- /dev/null +++ b/server/web/session/session_config_test.go @@ -0,0 +1,222 @@ +package session + +import ( + "net/http" + "testing" +) + +func TestCfgCookieLifeTime(t *testing.T) { + value := 8754 + c := NewManagerConfig( + CfgCookieLifeTime(value), + ) + + if c.CookieLifeTime != value { + t.Error() + } +} + +func TestCfgDomain(t *testing.T) { + value := `http://domain.com` + c := NewManagerConfig( + CfgDomain(value), + ) + + if c.Domain != value { + t.Error() + } +} + +func TestCfgSameSite(t *testing.T) { + value := http.SameSiteLaxMode + c := NewManagerConfig( + CfgSameSite(value), + ) + + if c.CookieSameSite != value { + t.Error() + } +} + +func TestCfgSecure(t *testing.T) { + c := NewManagerConfig( + CfgSecure(true), + ) + + if c.Secure != true { + t.Error() + } +} + +func TestCfgSecure1(t *testing.T) { + c := NewManagerConfig( + CfgSecure(false), + ) + + if c.Secure != false { + t.Error() + } +} + +func TestCfgSessionIdPrefix(t *testing.T) { + value := `sodiausodkljalsd` + c := NewManagerConfig( + CfgSessionIdPrefix(value), + ) + + if c.SessionIDPrefix != value { + t.Error() + } +} + +func TestCfgSetSessionNameInHTTPHeader(t *testing.T) { + value := `sodiausodkljalsd` + c := NewManagerConfig( + CfgSetSessionNameInHTTPHeader(value), + ) + + if c.SessionNameInHTTPHeader != value { + t.Error() + } +} + +func TestCfgCookieName(t *testing.T) { + value := `sodiausodkljalsd` + c := NewManagerConfig( + CfgCookieName(value), + ) + + if c.CookieName != value { + t.Error() + } +} + +func TestCfgEnableSidInURLQuery(t *testing.T) { + c := NewManagerConfig( + CfgEnableSidInURLQuery(true), + ) + + if c.EnableSidInURLQuery != true { + t.Error() + } +} + +func TestCfgGcLifeTime(t *testing.T) { + value := int64(5454) + c := NewManagerConfig( + CfgGcLifeTime(value), + ) + + if c.Gclifetime != value { + t.Error() + } +} + +func TestCfgHTTPOnly(t *testing.T) { + c := NewManagerConfig( + CfgHTTPOnly(true), + ) + + if c.DisableHTTPOnly != false { + t.Error() + } +} + +func TestCfgHTTPOnly2(t *testing.T) { + c := NewManagerConfig( + CfgHTTPOnly(false), + ) + + if c.DisableHTTPOnly != true { + t.Error() + } +} + +func TestCfgMaxLifeTime(t *testing.T) { + value := int64(5454) + c := NewManagerConfig( + CfgMaxLifeTime(value), + ) + + if c.Maxlifetime != value { + t.Error() + } +} + +func TestCfgProviderConfig(t *testing.T) { + value := `asodiuasldkj12i39809as` + c := NewManagerConfig( + CfgProviderConfig(value), + ) + + if c.ProviderConfig != value { + t.Error() + } +} + +func TestCfgSessionIdInHTTPHeader(t *testing.T) { + c := NewManagerConfig( + CfgSessionIdInHTTPHeader(true), + ) + + if c.EnableSidInHTTPHeader != true { + t.Error() + } +} + +func TestCfgSessionIdInHTTPHeader1(t *testing.T) { + c := NewManagerConfig( + CfgSessionIdInHTTPHeader(false), + ) + + if c.EnableSidInHTTPHeader != false { + t.Error() + } +} + +func TestCfgSessionIdLength(t *testing.T) { + value := int64(100) + c := NewManagerConfig( + CfgSessionIdLength(value), + ) + + if c.SessionIDLength != value { + t.Error() + } +} + +func TestCfgSetCookie(t *testing.T) { + c := NewManagerConfig( + CfgSetCookie(true), + ) + + if c.EnableSetCookie != true { + t.Error() + } +} + +func TestCfgSetCookie1(t *testing.T) { + c := NewManagerConfig( + CfgSetCookie(false), + ) + + if c.EnableSetCookie != false { + t.Error() + } +} + +func TestNewManagerConfig(t *testing.T) { + c := NewManagerConfig() + if c == nil { + t.Error() + } +} + +func TestManagerConfig_Opts(t *testing.T) { + c := NewManagerConfig() + c.Opts(CfgSetCookie(true)) + + if c.EnableSetCookie != true { + t.Error() + } +} \ No newline at end of file From 962eac05f62540b416a54325879b207eeb2ec73b Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 11:21:29 +0800 Subject: [PATCH 18/31] add storeKey supports --- server/web/filter/session/filter.go | 46 ++++++---- server/web/filter/session/filter_test.go | 102 ++++++++++++++++++++++- 2 files changed, 130 insertions(+), 18 deletions(-) diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go index b37a9f51..69bfaa9d 100644 --- a/server/web/filter/session/filter.go +++ b/server/web/filter/session/filter.go @@ -9,25 +9,30 @@ import ( webContext "github.com/beego/beego/v2/server/web/context" "github.com/beego/beego/v2/server/web/session" "github.com/google/uuid" - "sync" ) var ( - sessionKey string - sessionKeyOnce sync.Once + sessionFormatSign = uuid.New().ID() + defaultStorageKey = uuid.New().String() ) -func getSessionKey() string { - - sessionKeyOnce.Do(func() { - //generate an unique session store key - sessionKey = fmt.Sprintf(`sess_store:%d`, uuid.New().ID()) - }) - - return sessionKey +func sessionStoreKey(key string) string { + return fmt.Sprintf( + `sess_%d:%s`, + sessionFormatSign, + key, + ) } -func Session(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { +//Session maintain session for web service +//Session new a session storage and store it into webContext.Context +// +//params: +//ctx: pointer of beego web context +//storeName: set the storage key in ctx.Input +// +//if you want to get session storage, just see GetStore +func Session(providerType session.ProviderType, storeName string, options ...session.ManagerConfigOpt) web.FilterChain { sessionConfig := session.NewManagerConfig(options...) sessionManager, _ := session.NewManager(string(providerType), sessionConfig) go sessionManager.GC() @@ -40,7 +45,7 @@ func Session(providerType session.ProviderType, options ...session.ManagerConfig } else { //release session at the end of request defer sess.SessionRelease(context.Background(), ctx.ResponseWriter) - ctx.Input.SetData(getSessionKey(), sess) + ctx.Input.SetData(sessionStoreKey(storeName), sess) } next(ctx) @@ -49,13 +54,14 @@ func Session(providerType session.ProviderType, options ...session.ManagerConfig } } -func GetStore(ctx *webContext.Context) (store session.Store, err error) { +//GetStore get session storage in beego web context +func GetStore(ctx *webContext.Context, storeName string) (store session.Store, err error) { if ctx == nil { err = errors.New(`ctx is nil`) return } - if s, ok := ctx.Input.GetData(getSessionKey()).(session.Store); ok { + if s, ok := ctx.Input.GetData(sessionStoreKey(storeName)).(session.Store); ok { store = s return } else { @@ -63,3 +69,13 @@ func GetStore(ctx *webContext.Context) (store session.Store, err error) { return } } + +//DefaultSession call Session with default storage key +func DefaultSession(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { + return Session(providerType, defaultStorageKey, options...) +} + +//GetDefaultStore call GetStore with default storage key +func GetDefaultStore(ctx *webContext.Context) (store session.Store, err error) { + return GetStore(ctx, defaultStorageKey) +} diff --git a/server/web/filter/session/filter_test.go b/server/web/filter/session/filter_test.go index 7b24f6ad..ea4e7a6e 100644 --- a/server/web/filter/session/filter_test.go +++ b/server/web/filter/session/filter_test.go @@ -5,6 +5,7 @@ import ( "github.com/beego/beego/v2/server/web" webContext "github.com/beego/beego/v2/server/web/context" "github.com/beego/beego/v2/server/web/session" + "github.com/google/uuid" "net/http" "net/http/httptest" "testing" @@ -21,11 +22,13 @@ func testRequest(t *testing.T, handler *web.ControllerRegister, path string, met } func TestSession(t *testing.T) { + storeKey := uuid.New().String() handler := web.NewControllerRegister() handler.InsertFilterChain( "*", Session( session.ProviderMemory, + storeKey, session.CfgCookieName(`go_session_id`), session.CfgSetCookie(true), session.CfgGcLifeTime(3600), @@ -38,7 +41,7 @@ func TestSession(t *testing.T) { "*", func(next web.FilterFunc) web.FilterFunc { return func(ctx *webContext.Context) { - if store := ctx.Input.GetData(getSessionKey()); store == nil { + if store := ctx.Input.GetData(storeKey); store == nil { t.Error(`store should not be nil`) } next(ctx) @@ -53,11 +56,104 @@ func TestSession(t *testing.T) { } func TestGetStore(t *testing.T) { + storeKey := uuid.New().String() handler := web.NewControllerRegister() handler.InsertFilterChain( "*", Session( + session.ProviderMemory, + storeKey, + session.CfgCookieName(`go_session_id`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + var ( + checkKey = `asodiuasdk1j)AS(87` + checkValue = `ASsd-09812-3` + + store session.Store + err error + + c = context.Background() + ) + + if store, err = GetStore(ctx, storeKey); err == nil { + if store == nil { + t.Error(`store should not be nil`) + } else { + _ = store.Set(c, checkKey, checkValue) + } + } else { + t.Error(err) + } + + next(ctx) + + if store != nil { + if v := store.Get(c, checkKey); v != checkValue { + t.Error(v, `is not equals to`, checkValue) + } + } else { + t.Error(`store should not be nil`) + } + + } + }, + ) + handler.Any("*", func(ctx *webContext.Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} + +func TestDefaultSession(t *testing.T) { + handler := web.NewControllerRegister() + handler.InsertFilterChain( + "*", + DefaultSession( + session.ProviderMemory, + session.CfgCookieName(`go_session_id`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + if store := ctx.Input.GetData(defaultStorageKey); store == nil { + t.Error(`store should not be nil`) + } + next(ctx) + } + }, + ) + handler.Any("*", func(ctx *webContext.Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} + +func TestGetDefaultStore(t *testing.T) { + handler := web.NewControllerRegister() + + handler.InsertFilterChain( + "*", + DefaultSession( session.ProviderMemory, session.CfgCookieName(`go_session_id`), session.CfgSetCookie(true), @@ -81,7 +177,7 @@ func TestGetStore(t *testing.T) { c = context.Background() ) - if store, err = GetStore(ctx); err == nil { + if store, err = GetDefaultStore(ctx); err == nil { if store == nil { t.Error(`store should not be nil`) } else { @@ -97,7 +193,7 @@ func TestGetStore(t *testing.T) { if v := store.Get(c, checkKey); v != checkValue { t.Error(v, `is not equals to`, checkValue) } - }else{ + } else { t.Error(`store should not be nil`) } From c4b585741a23262a36d6df2f483131e6aecbb893 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 11:27:36 +0800 Subject: [PATCH 19/31] rename params --- server/web/filter/session/filter.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go index 69bfaa9d..2db1db88 100644 --- a/server/web/filter/session/filter.go +++ b/server/web/filter/session/filter.go @@ -29,10 +29,10 @@ func sessionStoreKey(key string) string { // //params: //ctx: pointer of beego web context -//storeName: set the storage key in ctx.Input +//storeKey: set the storage key in ctx.Input // //if you want to get session storage, just see GetStore -func Session(providerType session.ProviderType, storeName string, options ...session.ManagerConfigOpt) web.FilterChain { +func Session(providerType session.ProviderType, storeKey string, options ...session.ManagerConfigOpt) web.FilterChain { sessionConfig := session.NewManagerConfig(options...) sessionManager, _ := session.NewManager(string(providerType), sessionConfig) go sessionManager.GC() @@ -45,7 +45,7 @@ func Session(providerType session.ProviderType, storeName string, options ...ses } else { //release session at the end of request defer sess.SessionRelease(context.Background(), ctx.ResponseWriter) - ctx.Input.SetData(sessionStoreKey(storeName), sess) + ctx.Input.SetData(sessionStoreKey(storeKey), sess) } next(ctx) @@ -55,13 +55,13 @@ func Session(providerType session.ProviderType, storeName string, options ...ses } //GetStore get session storage in beego web context -func GetStore(ctx *webContext.Context, storeName string) (store session.Store, err error) { +func GetStore(ctx *webContext.Context, storeKey string) (store session.Store, err error) { if ctx == nil { err = errors.New(`ctx is nil`) return } - if s, ok := ctx.Input.GetData(sessionStoreKey(storeName)).(session.Store); ok { + if s, ok := ctx.Input.GetData(sessionStoreKey(storeKey)).(session.Store); ok { store = s return } else { From d7b79f23a6afcfc5cdecebea1098eae2f48840c4 Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Sat, 9 Jan 2021 21:15:48 +0800 Subject: [PATCH 20/31] Add sonar check action --- .github/workflows/sonar.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/sonar.yml diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml new file mode 100644 index 00000000..9c63eaac --- /dev/null +++ b/.github/workflows/sonar.yml @@ -0,0 +1,19 @@ +on: + # Trigger analysis when pushing in master or pull requests, and when creating + # a pull request. + pull_request: + types: [opened, synchronize, reopened] +name: Main Workflow +jobs: + sonarcloud: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting + fetch-depth: 0 + - name: SonarCloud Scan + uses: sonarsource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From 0cf3b035ebf0ab74023324aa23e1f5ca5974d5ac Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Fri, 8 Jan 2021 22:54:39 +0800 Subject: [PATCH 21/31] update changelog --- .github/workflows/changelog.yml | 2 +- CHANGELOG.md | 1 + server/web/filter/prometheus/filter_test.go | 2 ++ task/task_test.go | 17 +++++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 7e4b1032..50e91510 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -8,7 +8,7 @@ on: pull_request: types: [opened, synchronize, reopened, labeled, unlabeled] branches: - - master + - develop jobs: changelog: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a259efc..14c40055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # developing +- Update changlog.yml to check every PR to develop branch.[4427](https://github.com/beego/beego/pull/4427) - Fix 4396: Add context.param module into adapter. [4398](https://github.com/beego/beego/pull/4398) - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) - Fix `unknown escape sequence` in generated code. [4385](https://github.com/beego/beego/pull/4385) diff --git a/server/web/filter/prometheus/filter_test.go b/server/web/filter/prometheus/filter_test.go index f00f20e7..be008d41 100644 --- a/server/web/filter/prometheus/filter_test.go +++ b/server/web/filter/prometheus/filter_test.go @@ -18,6 +18,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" "github.com/stretchr/testify/assert" @@ -37,4 +38,5 @@ func TestFilterChain(t *testing.T) { ctx.Input.SetData("RouterPattern", "my-route") filter(ctx) assert.True(t, ctx.Input.GetData("invocation").(bool)) + time.Sleep(1 * time.Second) } diff --git a/task/task_test.go b/task/task_test.go index 5e117cbd..c87757ef 100644 --- a/task/task_test.go +++ b/task/task_test.go @@ -109,6 +109,23 @@ func TestTask_Run(t *testing.T) { assert.Equal(t, "Hello, world! 101", l[1].errinfo) } +func TestCrudTask(t *testing.T) { + m := newTaskManager() + m.AddTask("my-task1", NewTask("my-task1", "0/30 * * * * *", func(ctx context.Context) error { + return nil + })) + + m.AddTask("my-task2", NewTask("my-task2", "0/30 * * * * *", func(ctx context.Context) error { + return nil + })) + + m.DeleteTask("my-task1") + assert.Equal(t, 1, len(m.adminTaskList)) + + m.ClearTask() + assert.Equal(t, 0, len(m.adminTaskList)) +} + func wait(wg *sync.WaitGroup) chan bool { ch := make(chan bool) go func() { From 3150285542bd2339030a92e8cfedf6736038f6ff Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 21:27:30 +0800 Subject: [PATCH 22/31] fix imports --- client/orm/db_tables.go | 4 ++-- client/orm/orm_queryset.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/orm/db_tables.go b/client/orm/db_tables.go index 82b8ab7e..d62d8106 100644 --- a/client/orm/db_tables.go +++ b/client/orm/db_tables.go @@ -16,8 +16,8 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/clauses" - "github.com/astaxie/beego/client/orm/clauses/order_clause" + "github.com/beego/beego/v2/client/orm/clauses" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "strings" "time" ) diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 9f7a3c1e..66e1c442 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -17,8 +17,8 @@ package orm import ( "context" "fmt" - "github.com/astaxie/beego/v2/client/orm/hints" - "github.com/astaxie/beego/v2/client/orm/clauses/order_clause" + "github.com/beego/beego/v2/client/orm/hints" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" ) type colValue struct { From 791c28b1d4a5ec03207d912d550f9cf8e8fec238 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 22:16:21 +0800 Subject: [PATCH 23/31] fix imports --- client/orm/clauses/order_clause/order.go | 2 +- client/orm/orm.go | 2 +- client/orm/orm_conds.go | 2 +- client/orm/orm_test.go | 2 +- client/orm/types.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/orm/clauses/order_clause/order.go b/client/orm/clauses/order_clause/order.go index 510c5505..e45c2f85 100644 --- a/client/orm/clauses/order_clause/order.go +++ b/client/orm/clauses/order_clause/order.go @@ -1,7 +1,7 @@ package order_clause import ( - "github.com/astaxie/beego/client/orm/clauses" + "github.com/beego/beego/v2/client/orm/clauses" "strings" ) diff --git a/client/orm/orm.go b/client/orm/orm.go index f4422648..f33c4b51 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -58,7 +58,7 @@ import ( "database/sql" "errors" "fmt" - "github.com/astaxie/beego/client/orm/clauses/order_clause" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "os" "reflect" "time" diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index 99828f3c..0080d53c 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -16,7 +16,7 @@ package orm import ( "fmt" - "github.com/astaxie/beego/client/orm/clauses" + "github.com/beego/beego/v2/client/orm/clauses" "strings" ) diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index 1dd3bc8d..f2943739 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -21,7 +21,7 @@ import ( "context" "database/sql" "fmt" - "github.com/astaxie/beego/client/orm/clauses/order_clause" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "io/ioutil" "math" "os" diff --git a/client/orm/types.go b/client/orm/types.go index 37aa9f3f..b22848fe 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -17,7 +17,7 @@ package orm import ( "context" "database/sql" - "github.com/astaxie/beego/client/orm/clauses/order_clause" + "github.com/beego/beego/v2/client/orm/clauses/order_clause" "reflect" "time" From a98edc03cd321611308b3101a38cdecca30773e1 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 23:39:16 +0800 Subject: [PATCH 24/31] adapt CruSession --- server/web/filter/session/filter.go | 36 ++------- server/web/filter/session/filter_test.go | 96 +----------------------- server/web/session/session.go | 5 +- 3 files changed, 12 insertions(+), 125 deletions(-) diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go index 2db1db88..685f86c1 100644 --- a/server/web/filter/session/filter.go +++ b/server/web/filter/session/filter.go @@ -3,27 +3,12 @@ package session import ( "context" "errors" - "fmt" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" webContext "github.com/beego/beego/v2/server/web/context" "github.com/beego/beego/v2/server/web/session" - "github.com/google/uuid" ) -var ( - sessionFormatSign = uuid.New().ID() - defaultStorageKey = uuid.New().String() -) - -func sessionStoreKey(key string) string { - return fmt.Sprintf( - `sess_%d:%s`, - sessionFormatSign, - key, - ) -} - //Session maintain session for web service //Session new a session storage and store it into webContext.Context // @@ -32,20 +17,23 @@ func sessionStoreKey(key string) string { //storeKey: set the storage key in ctx.Input // //if you want to get session storage, just see GetStore -func Session(providerType session.ProviderType, storeKey string, options ...session.ManagerConfigOpt) web.FilterChain { +func Session(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { sessionConfig := session.NewManagerConfig(options...) sessionManager, _ := session.NewManager(string(providerType), sessionConfig) go sessionManager.GC() return func(next web.FilterFunc) web.FilterFunc { return func(ctx *webContext.Context) { + if ctx.Input.CruSession != nil { + return + } if sess, err := sessionManager.SessionStart(ctx.ResponseWriter, ctx.Request); err != nil { logs.Warning(`init session error:%s`, err.Error()) } else { //release session at the end of request defer sess.SessionRelease(context.Background(), ctx.ResponseWriter) - ctx.Input.SetData(sessionStoreKey(storeKey), sess) + ctx.Input.CruSession = sess } next(ctx) @@ -55,13 +43,13 @@ func Session(providerType session.ProviderType, storeKey string, options ...sess } //GetStore get session storage in beego web context -func GetStore(ctx *webContext.Context, storeKey string) (store session.Store, err error) { +func GetStore(ctx *webContext.Context) (store session.Store, err error) { if ctx == nil { err = errors.New(`ctx is nil`) return } - if s, ok := ctx.Input.GetData(sessionStoreKey(storeKey)).(session.Store); ok { + if s := ctx.Input.CruSession; s != nil { store = s return } else { @@ -69,13 +57,3 @@ func GetStore(ctx *webContext.Context, storeKey string) (store session.Store, er return } } - -//DefaultSession call Session with default storage key -func DefaultSession(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { - return Session(providerType, defaultStorageKey, options...) -} - -//GetDefaultStore call GetStore with default storage key -func GetDefaultStore(ctx *webContext.Context) (store session.Store, err error) { - return GetStore(ctx, defaultStorageKey) -} diff --git a/server/web/filter/session/filter_test.go b/server/web/filter/session/filter_test.go index ea4e7a6e..7e38cdc2 100644 --- a/server/web/filter/session/filter_test.go +++ b/server/web/filter/session/filter_test.go @@ -28,7 +28,6 @@ func TestSession(t *testing.T) { "*", Session( session.ProviderMemory, - storeKey, session.CfgCookieName(`go_session_id`), session.CfgSetCookie(true), session.CfgGcLifeTime(3600), @@ -56,14 +55,12 @@ func TestSession(t *testing.T) { } func TestGetStore(t *testing.T) { - storeKey := uuid.New().String() handler := web.NewControllerRegister() handler.InsertFilterChain( "*", Session( session.ProviderMemory, - storeKey, session.CfgCookieName(`go_session_id`), session.CfgSetCookie(true), session.CfgGcLifeTime(3600), @@ -86,98 +83,7 @@ func TestGetStore(t *testing.T) { c = context.Background() ) - if store, err = GetStore(ctx, storeKey); err == nil { - if store == nil { - t.Error(`store should not be nil`) - } else { - _ = store.Set(c, checkKey, checkValue) - } - } else { - t.Error(err) - } - - next(ctx) - - if store != nil { - if v := store.Get(c, checkKey); v != checkValue { - t.Error(v, `is not equals to`, checkValue) - } - } else { - t.Error(`store should not be nil`) - } - - } - }, - ) - handler.Any("*", func(ctx *webContext.Context) { - ctx.Output.SetStatus(200) - }) - - testRequest(t, handler, "/dataset1/resource1", "GET", 200) -} - -func TestDefaultSession(t *testing.T) { - handler := web.NewControllerRegister() - handler.InsertFilterChain( - "*", - DefaultSession( - session.ProviderMemory, - session.CfgCookieName(`go_session_id`), - session.CfgSetCookie(true), - session.CfgGcLifeTime(3600), - session.CfgMaxLifeTime(3600), - session.CfgSecure(false), - session.CfgCookieLifeTime(3600), - ), - ) - handler.InsertFilterChain( - "*", - func(next web.FilterFunc) web.FilterFunc { - return func(ctx *webContext.Context) { - if store := ctx.Input.GetData(defaultStorageKey); store == nil { - t.Error(`store should not be nil`) - } - next(ctx) - } - }, - ) - handler.Any("*", func(ctx *webContext.Context) { - ctx.Output.SetStatus(200) - }) - - testRequest(t, handler, "/dataset1/resource1", "GET", 200) -} - -func TestGetDefaultStore(t *testing.T) { - handler := web.NewControllerRegister() - - handler.InsertFilterChain( - "*", - DefaultSession( - session.ProviderMemory, - session.CfgCookieName(`go_session_id`), - session.CfgSetCookie(true), - session.CfgGcLifeTime(3600), - session.CfgMaxLifeTime(3600), - session.CfgSecure(false), - session.CfgCookieLifeTime(3600), - ), - ) - handler.InsertFilterChain( - "*", - func(next web.FilterFunc) web.FilterFunc { - return func(ctx *webContext.Context) { - var ( - checkKey = `asodiuasdk1j)AS(87` - checkValue = `ASsd-09812-3` - - store session.Store - err error - - c = context.Background() - ) - - if store, err = GetDefaultStore(ctx); err == nil { + if store, err = GetStore(ctx); err == nil { if store == nil { t.Error(`store should not be nil`) } else { diff --git a/server/web/session/session.go b/server/web/session/session.go index ca0407e8..911f45fe 100644 --- a/server/web/session/session.go +++ b/server/web/session/session.go @@ -279,7 +279,10 @@ func (manager *Manager) GetSessionStore(sid string) (sessions Store, err error) // it can do gc in times after gc lifetime. func (manager *Manager) GC() { manager.provider.SessionGC(nil) - time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() }) + ticker := time.NewTicker(time.Duration(manager.config.Gclifetime) * time.Second) + for range ticker.C { + manager.provider.SessionGC(nil) + } } // SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request. From 25bf1259c61bea15c04c92228cc15f64dc18dd66 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sat, 9 Jan 2021 23:55:18 +0800 Subject: [PATCH 25/31] add change log --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a259efc..28cdd2f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,4 +3,5 @@ - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) - Fix `unknown escape sequence` in generated code. [4385](https://github.com/beego/beego/pull/4385) - Using fixed name `commentRouter.go` as generated file name. [4385](https://github.com/beego/beego/pull/4385) -- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386) \ No newline at end of file +- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386) +- Support 4144: Add new api for order by for supporting multiple way to query [4294](https://github.com/beego/beego/pull/4294) \ No newline at end of file From 1f475585e55e5c710f95d25d974d7e44b58b62ec Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 10 Jan 2021 00:33:53 +0800 Subject: [PATCH 26/31] change log level and recover code --- CHANGELOG.md | 3 ++- server/web/filter/session/filter.go | 2 +- server/web/session/session.go | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a259efc..6e9c6c1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,4 +3,5 @@ - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) - Fix `unknown escape sequence` in generated code. [4385](https://github.com/beego/beego/pull/4385) - Using fixed name `commentRouter.go` as generated file name. [4385](https://github.com/beego/beego/pull/4385) -- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386) \ No newline at end of file +- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386) +- Support session Filter chain. [4404](https://github.com/beego/beego/pull/4404) \ No newline at end of file diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go index 685f86c1..1776d604 100644 --- a/server/web/filter/session/filter.go +++ b/server/web/filter/session/filter.go @@ -29,7 +29,7 @@ func Session(providerType session.ProviderType, options ...session.ManagerConfig } if sess, err := sessionManager.SessionStart(ctx.ResponseWriter, ctx.Request); err != nil { - logs.Warning(`init session error:%s`, err.Error()) + logs.Error(`init session error:%s`, err.Error()) } else { //release session at the end of request defer sess.SessionRelease(context.Background(), ctx.ResponseWriter) diff --git a/server/web/session/session.go b/server/web/session/session.go index 911f45fe..ca0407e8 100644 --- a/server/web/session/session.go +++ b/server/web/session/session.go @@ -279,10 +279,7 @@ func (manager *Manager) GetSessionStore(sid string) (sessions Store, err error) // it can do gc in times after gc lifetime. func (manager *Manager) GC() { manager.provider.SessionGC(nil) - ticker := time.NewTicker(time.Duration(manager.config.Gclifetime) * time.Second) - for range ticker.C { - manager.provider.SessionGC(nil) - } + time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() }) } // SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request. From 2590fbd5cb1276cbd220db08542c5a56478a6b9b Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Sat, 9 Jan 2021 21:36:30 +0800 Subject: [PATCH 27/31] Fix sonar check --- .github/workflows/sonar.yml | 13 ++++++++----- CHANGELOG.md | 1 + sonar-project.properties | 6 ++++++ 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 sonar-project.properties diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 9c63eaac..1a3b927a 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -1,9 +1,15 @@ on: # Trigger analysis when pushing in master or pull requests, and when creating # a pull request. + push: + branches: + - develop pull_request: types: [opened, synchronize, reopened] -name: Main Workflow +name: Sonar Check +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} jobs: sonarcloud: runs-on: ubuntu-latest @@ -13,7 +19,4 @@ jobs: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 - name: SonarCloud Scan - uses: sonarsource/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file + uses: sonarsource/sonarcloud-github-action@master \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 14c40055..ec59f070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # developing +- Add sonar check. [4432](https://github.com/beego/beego/pull/4432) - Update changlog.yml to check every PR to develop branch.[4427](https://github.com/beego/beego/pull/4427) - Fix 4396: Add context.param module into adapter. [4398](https://github.com/beego/beego/pull/4398) - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000..2fc78d8d --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,6 @@ +sonar.organization=beego +sonar.projectKey=beego_beego + +# relative paths to source directories. More details and properties are described +# in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/ +sonar.sources=. \ No newline at end of file From eed869a29671aa2732a52a36ed650754795e0ac5 Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Sun, 10 Jan 2021 13:20:55 +0800 Subject: [PATCH 28/31] Remove sonar --- .github/workflows/sonar.yml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .github/workflows/sonar.yml diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml deleted file mode 100644 index 1a3b927a..00000000 --- a/.github/workflows/sonar.yml +++ /dev/null @@ -1,22 +0,0 @@ -on: - # Trigger analysis when pushing in master or pull requests, and when creating - # a pull request. - push: - branches: - - develop - pull_request: - types: [opened, synchronize, reopened] -name: Sonar Check -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -jobs: - sonarcloud: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - # Disabling shallow clone is recommended for improving relevancy of reporting - fetch-depth: 0 - - name: SonarCloud Scan - uses: sonarsource/sonarcloud-github-action@master \ No newline at end of file From 31f79c2ee2baecda21fe17b469739fd8915b82b9 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 10 Jan 2021 13:50:43 +0800 Subject: [PATCH 29/31] move getting session store to web context --- server/web/context/context.go | 17 +++++++ server/web/context/context_test.go | 46 ++++++++++++++++++ server/web/filter/session/filter.go | 26 +--------- server/web/filter/session/filter_test.go | 60 ------------------------ 4 files changed, 64 insertions(+), 85 deletions(-) diff --git a/server/web/context/context.go b/server/web/context/context.go index 6070c996..edbf14f5 100644 --- a/server/web/context/context.go +++ b/server/web/context/context.go @@ -29,6 +29,7 @@ import ( "encoding/base64" "errors" "fmt" + "github.com/beego/beego/v2/server/web/session" "net" "net/http" "strconv" @@ -195,6 +196,22 @@ func (ctx *Context) RenderMethodResult(result interface{}) { } } +// Session return session store of this context of request +func (ctx *Context) Session() (store session.Store,err error){ + if ctx.Input != nil { + if ctx.Input.CruSession != nil { + store = ctx.Input.CruSession + return + } else { + err = errors.New(`no valid session store(please initialize session)`) + return + } + } else { + err = errors.New(`no valid input`) + return + } +} + // Response is a wrapper for the http.ResponseWriter // Started: if true, response was already written to so the other handler will not be executed type Response struct { diff --git a/server/web/context/context_test.go b/server/web/context/context_test.go index 7c0535e0..7fdb310f 100644 --- a/server/web/context/context_test.go +++ b/server/web/context/context_test.go @@ -15,6 +15,9 @@ package context import ( + "github.com/beego/beego/v2/server/web" + "github.com/beego/beego/v2/server/web/filter/session" + webSession "github.com/beego/beego/v2/server/web/session" "net/http" "net/http/httptest" "testing" @@ -45,3 +48,46 @@ func TestXsrfReset_01(t *testing.T) { t.FailNow() } } + +func testRequest(t *testing.T, handler *web.ControllerRegister, path string, method string, code int) { + r, _ := http.NewRequest(method, path, nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + if w.Code != code { + t.Errorf("%s, %s: %d, supposed to be %d", path, method, w.Code, code) + } +} + +func TestContext_Session(t *testing.T) { + handler := web.NewControllerRegister() + + handler.InsertFilterChain( + "*", + session.Session( + webSession.ProviderMemory, + webSession.CfgCookieName(`go_session_id`), + webSession.CfgSetCookie(true), + webSession.CfgGcLifeTime(3600), + webSession.CfgMaxLifeTime(3600), + webSession.CfgSecure(false), + webSession.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *Context) { + if _, err := ctx.Session(); err == nil { + t.Error() + } + + } + }, + ) + handler.Any("*", func(ctx *Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} \ No newline at end of file diff --git a/server/web/filter/session/filter.go b/server/web/filter/session/filter.go index 1776d604..bcf9edf4 100644 --- a/server/web/filter/session/filter.go +++ b/server/web/filter/session/filter.go @@ -2,7 +2,6 @@ package session import ( "context" - "errors" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" webContext "github.com/beego/beego/v2/server/web/context" @@ -11,12 +10,6 @@ import ( //Session maintain session for web service //Session new a session storage and store it into webContext.Context -// -//params: -//ctx: pointer of beego web context -//storeKey: set the storage key in ctx.Input -// -//if you want to get session storage, just see GetStore func Session(providerType session.ProviderType, options ...session.ManagerConfigOpt) web.FilterChain { sessionConfig := session.NewManagerConfig(options...) sessionManager, _ := session.NewManager(string(providerType), sessionConfig) @@ -37,23 +30,6 @@ func Session(providerType session.ProviderType, options ...session.ManagerConfig } next(ctx) - } } -} - -//GetStore get session storage in beego web context -func GetStore(ctx *webContext.Context) (store session.Store, err error) { - if ctx == nil { - err = errors.New(`ctx is nil`) - return - } - - if s := ctx.Input.CruSession; s != nil { - store = s - return - } else { - err = errors.New(`can not get a valid session store`) - return - } -} +} \ No newline at end of file diff --git a/server/web/filter/session/filter_test.go b/server/web/filter/session/filter_test.go index 7e38cdc2..03a88afd 100644 --- a/server/web/filter/session/filter_test.go +++ b/server/web/filter/session/filter_test.go @@ -1,7 +1,6 @@ package session import ( - "context" "github.com/beego/beego/v2/server/web" webContext "github.com/beego/beego/v2/server/web/context" "github.com/beego/beego/v2/server/web/session" @@ -53,62 +52,3 @@ func TestSession(t *testing.T) { testRequest(t, handler, "/dataset1/resource1", "GET", 200) } - -func TestGetStore(t *testing.T) { - handler := web.NewControllerRegister() - - handler.InsertFilterChain( - "*", - Session( - session.ProviderMemory, - session.CfgCookieName(`go_session_id`), - session.CfgSetCookie(true), - session.CfgGcLifeTime(3600), - session.CfgMaxLifeTime(3600), - session.CfgSecure(false), - session.CfgCookieLifeTime(3600), - ), - ) - handler.InsertFilterChain( - "*", - func(next web.FilterFunc) web.FilterFunc { - return func(ctx *webContext.Context) { - var ( - checkKey = `asodiuasdk1j)AS(87` - checkValue = `ASsd-09812-3` - - store session.Store - err error - - c = context.Background() - ) - - if store, err = GetStore(ctx); err == nil { - if store == nil { - t.Error(`store should not be nil`) - } else { - _ = store.Set(c, checkKey, checkValue) - } - } else { - t.Error(err) - } - - next(ctx) - - if store != nil { - if v := store.Get(c, checkKey); v != checkValue { - t.Error(v, `is not equals to`, checkValue) - } - } else { - t.Error(`store should not be nil`) - } - - } - }, - ) - handler.Any("*", func(ctx *webContext.Context) { - ctx.Output.SetStatus(200) - }) - - testRequest(t, handler, "/dataset1/resource1", "GET", 200) -} From 87ffa0b730d4f6fe96a880adb26393bd1dd4b0f3 Mon Sep 17 00:00:00 2001 From: Anker Jam Date: Sun, 10 Jan 2021 14:22:11 +0800 Subject: [PATCH 30/31] fix UT --- server/web/context/context.go | 2 +- server/web/context/context_test.go | 56 +++++++----------------- server/web/filter/session/filter_test.go | 32 ++++++++++++++ 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/server/web/context/context.go b/server/web/context/context.go index edbf14f5..099729d0 100644 --- a/server/web/context/context.go +++ b/server/web/context/context.go @@ -197,7 +197,7 @@ func (ctx *Context) RenderMethodResult(result interface{}) { } // Session return session store of this context of request -func (ctx *Context) Session() (store session.Store,err error){ +func (ctx *Context) Session() (store session.Store, err error) { if ctx.Input != nil { if ctx.Input.CruSession != nil { store = ctx.Input.CruSession diff --git a/server/web/context/context_test.go b/server/web/context/context_test.go index 7fdb310f..977c3cbf 100644 --- a/server/web/context/context_test.go +++ b/server/web/context/context_test.go @@ -15,9 +15,7 @@ package context import ( - "github.com/beego/beego/v2/server/web" - "github.com/beego/beego/v2/server/web/filter/session" - webSession "github.com/beego/beego/v2/server/web/session" + "github.com/beego/beego/v2/server/web/session" "net/http" "net/http/httptest" "testing" @@ -49,45 +47,25 @@ func TestXsrfReset_01(t *testing.T) { } } -func testRequest(t *testing.T, handler *web.ControllerRegister, path string, method string, code int) { - r, _ := http.NewRequest(method, path, nil) - w := httptest.NewRecorder() - handler.ServeHTTP(w, r) - - if w.Code != code { - t.Errorf("%s, %s: %d, supposed to be %d", path, method, w.Code, code) +func TestContext_Session(t *testing.T) { + c := NewContext() + if store, err := c.Session(); store != nil || err == nil { + t.FailNow() } } -func TestContext_Session(t *testing.T) { - handler := web.NewControllerRegister() +func TestContext_Session1(t *testing.T) { + c := Context{} + if store, err := c.Session(); store != nil || err == nil { + t.FailNow() + } +} - handler.InsertFilterChain( - "*", - session.Session( - webSession.ProviderMemory, - webSession.CfgCookieName(`go_session_id`), - webSession.CfgSetCookie(true), - webSession.CfgGcLifeTime(3600), - webSession.CfgMaxLifeTime(3600), - webSession.CfgSecure(false), - webSession.CfgCookieLifeTime(3600), - ), - ) - handler.InsertFilterChain( - "*", - func(next web.FilterFunc) web.FilterFunc { - return func(ctx *Context) { - if _, err := ctx.Session(); err == nil { - t.Error() - } +func TestContext_Session2(t *testing.T) { + c := NewContext() + c.Input.CruSession = &session.MemSessionStore{} - } - }, - ) - handler.Any("*", func(ctx *Context) { - ctx.Output.SetStatus(200) - }) - - testRequest(t, handler, "/dataset1/resource1", "GET", 200) + if store, err := c.Session(); store == nil || err != nil { + t.FailNow() + } } \ No newline at end of file diff --git a/server/web/filter/session/filter_test.go b/server/web/filter/session/filter_test.go index 03a88afd..687789a5 100644 --- a/server/web/filter/session/filter_test.go +++ b/server/web/filter/session/filter_test.go @@ -52,3 +52,35 @@ func TestSession(t *testing.T) { testRequest(t, handler, "/dataset1/resource1", "GET", 200) } + +func TestSession1(t *testing.T) { + handler := web.NewControllerRegister() + handler.InsertFilterChain( + "*", + Session( + session.ProviderMemory, + session.CfgCookieName(`go_session_id`), + session.CfgSetCookie(true), + session.CfgGcLifeTime(3600), + session.CfgMaxLifeTime(3600), + session.CfgSecure(false), + session.CfgCookieLifeTime(3600), + ), + ) + handler.InsertFilterChain( + "*", + func(next web.FilterFunc) web.FilterFunc { + return func(ctx *webContext.Context) { + if store, err := ctx.Session(); store == nil || err != nil { + t.Error(`store should not be nil`) + } + next(ctx) + } + }, + ) + handler.Any("*", func(ctx *webContext.Context) { + ctx.Output.SetStatus(200) + }) + + testRequest(t, handler, "/dataset1/resource1", "GET", 200) +} From 95e998e36e26a80003575928757f35afde7ebf9a Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Sun, 10 Jan 2021 18:13:00 +0800 Subject: [PATCH 31/31] sonar ignore test --- CHANGELOG.md | 2 +- sonar-project.properties | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bde738f..2d98d10d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # developing -- Add sonar check. [4432](https://github.com/beego/beego/pull/4432) +- Add sonar check and ignore test. [4432](https://github.com/beego/beego/pull/4432) [4433](https://github.com/beego/beego/pull/4433) - Update changlog.yml to check every PR to develop branch.[4427](https://github.com/beego/beego/pull/4427) - Fix 4396: Add context.param module into adapter. [4398](https://github.com/beego/beego/pull/4398) - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) diff --git a/sonar-project.properties b/sonar-project.properties index 2fc78d8d..1a12fb33 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,4 +3,5 @@ sonar.projectKey=beego_beego # relative paths to source directories. More details and properties are described # in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/ -sonar.sources=. \ No newline at end of file +sonar.sources=. +sonar.exclusions=**/*_test.go \ No newline at end of file