diff --git a/docs/api_docs/bundle.yaml b/docs/api_docs/bundle.yaml index ce2d0d2d..2f6859d3 100644 --- a/docs/api_docs/bundle.yaml +++ b/docs/api_docs/bundle.yaml @@ -800,6 +800,13 @@ paths: type: integer format: int64 description: return snapshots given the offset, it should usually set together with limit + - in: query + name: sort + type: string + enum: + - ASC + - DESC + description: sort order responses: '200': description: returns the flag snapshots diff --git a/pkg/handler/crud.go b/pkg/handler/crud.go index f24c5f97..64f2d4d0 100644 --- a/pkg/handler/crud.go +++ b/pkg/handler/crud.go @@ -18,6 +18,7 @@ import ( "github.com/go-openapi/runtime/middleware" "gorm.io/gorm" + "gorm.io/gorm/clause" ) // CRUD is the CRUD interface @@ -180,8 +181,18 @@ func (c *crud) GetFlagSnapshots(params flag.GetFlagSnapshotsParams) middleware.R tx = tx.Offset(int(*params.Offset)) } + descending := true + if params.Sort != nil && *params.Sort == "ASC" { + descending = false + } + if err := tx. - Order("created_at desc"). + Order(clause.OrderByColumn{ + Column: clause.Column{ + Name: "created_at", + }, + Desc: descending, + }). Where(entity.FlagSnapshot{FlagID: util.SafeUint(params.FlagID)}). Find(&fs).Error; err != nil { return flag.NewGetFlagSnapshotsDefault(500).WithPayload( diff --git a/pkg/handler/crud_test.go b/pkg/handler/crud_test.go index f6a4f5bc..571bdbe7 100644 --- a/pkg/handler/crud_test.go +++ b/pkg/handler/crud_test.go @@ -1,6 +1,7 @@ package handler import ( + "encoding/json" "fmt" "testing" @@ -476,19 +477,25 @@ func TestGetFlagSnapshots(t *testing.T) { defer tmpDB.Close() defer gostub.StubFunc(&getDB, db).Reset() - c.CreateFlag(flag.CreateFlagParams{ - Body: &models.CreateFlagRequest{ - Description: util.StringPtr("funny flag"), - }, - }) + f := entity.Flag{} + err := db.Create(&f).Error + assert.NoError(t, err) + + fb, err := json.Marshal(f) + assert.NoError(t, err) for i := 0; i < numOfSnapshots; i++ { - entity.SaveFlagSnapshot(db, 1, "flagr-test@example.com") + snapshot := entity.FlagSnapshot{ + FlagID: 1, + Flag: fb, + } + err := db.Create(&snapshot).Error + assert.NoError(t, err) } t.Run("GetFlagSnapshots - got all the results", func(t *testing.T) { res = c.GetFlagSnapshots(flag.GetFlagSnapshotsParams{}) - assert.Len(t, res.(*flag.GetFlagSnapshotsOK).Payload, numOfSnapshots+1) + assert.Len(t, res.(*flag.GetFlagSnapshotsOK).Payload, numOfSnapshots) }) t.Run("GetFlagSnapshots (with limit)", func(t *testing.T) { @@ -504,8 +511,28 @@ func TestGetFlagSnapshots(t *testing.T) { Offset: util.Int64Ptr(int64(2)), }) assert.Len(t, res.(*flag.GetFlagSnapshotsOK).Payload, 2) - assert.Equal(t, int64(9), res.(*flag.GetFlagSnapshotsOK).Payload[0].ID) - assert.Equal(t, int64(8), res.(*flag.GetFlagSnapshotsOK).Payload[1].ID) + assert.Equal(t, int64(8), res.(*flag.GetFlagSnapshotsOK).Payload[0].ID) + assert.Equal(t, int64(7), res.(*flag.GetFlagSnapshotsOK).Payload[1].ID) + }) + + t.Run("GetFlagSnapshots (sort ascending)", func(t *testing.T) { + res = c.GetFlagSnapshots(flag.GetFlagSnapshotsParams{ + Limit: util.Int64Ptr(int64(2)), + Sort: util.StringPtr("ASC"), + }) + assert.Len(t, res.(*flag.GetFlagSnapshotsOK).Payload, 2) + assert.Equal(t, int64(1), res.(*flag.GetFlagSnapshotsOK).Payload[0].ID) + assert.Equal(t, int64(2), res.(*flag.GetFlagSnapshotsOK).Payload[1].ID) + }) + + t.Run("GetFlagSnapshots (sort descending)", func(t *testing.T) { + res = c.GetFlagSnapshots(flag.GetFlagSnapshotsParams{ + Limit: util.Int64Ptr(int64(2)), + Sort: util.StringPtr("DESC"), + }) + assert.Len(t, res.(*flag.GetFlagSnapshotsOK).Payload, 2) + assert.Equal(t, int64(10), res.(*flag.GetFlagSnapshotsOK).Payload[0].ID) + assert.Equal(t, int64(9), res.(*flag.GetFlagSnapshotsOK).Payload[1].ID) }) } diff --git a/swagger/flag_snapshots.yaml b/swagger/flag_snapshots.yaml index 9cae19ef..139a7bd7 100644 --- a/swagger/flag_snapshots.yaml +++ b/swagger/flag_snapshots.yaml @@ -20,6 +20,13 @@ get: type: integer format: int64 description: return snapshots given the offset, it should usually set together with limit + - in: query + name: sort + type: string + enum: + - ASC + - DESC + description: sort order responses: 200: description: returns the flag snapshots diff --git a/swagger_gen/restapi/embedded_spec.go b/swagger_gen/restapi/embedded_spec.go index 6b60238d..d3daaf85 100644 --- a/swagger_gen/restapi/embedded_spec.go +++ b/swagger_gen/restapi/embedded_spec.go @@ -1007,6 +1007,16 @@ func init() { "description": "return snapshots given the offset, it should usually set together with limit", "name": "offset", "in": "query" + }, + { + "enum": [ + "ASC", + "DESC" + ], + "type": "string", + "description": "sort order", + "name": "sort", + "in": "query" } ], "responses": { @@ -3086,6 +3096,16 @@ func init() { "description": "return snapshots given the offset, it should usually set together with limit", "name": "offset", "in": "query" + }, + { + "enum": [ + "ASC", + "DESC" + ], + "type": "string", + "description": "sort order", + "name": "sort", + "in": "query" } ], "responses": { diff --git a/swagger_gen/restapi/operations/flag/get_flag_snapshots_parameters.go b/swagger_gen/restapi/operations/flag/get_flag_snapshots_parameters.go index a755affc..b38bd182 100644 --- a/swagger_gen/restapi/operations/flag/get_flag_snapshots_parameters.go +++ b/swagger_gen/restapi/operations/flag/get_flag_snapshots_parameters.go @@ -47,6 +47,10 @@ type GetFlagSnapshotsParams struct { In: query */ Offset *int64 + /*sort order + In: query + */ + Sort *string } // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface @@ -74,6 +78,11 @@ func (o *GetFlagSnapshotsParams) BindRequest(r *http.Request, route *middleware. if err := o.bindOffset(qOffset, qhkOffset, route.Formats); err != nil { res = append(res, err) } + + qSort, qhkSort, _ := qs.GetOK("sort") + if err := o.bindSort(qSort, qhkSort, route.Formats); err != nil { + res = append(res, err) + } if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -158,3 +167,35 @@ func (o *GetFlagSnapshotsParams) bindOffset(rawData []string, hasKey bool, forma return nil } + +// bindSort binds and validates parameter Sort from query. +func (o *GetFlagSnapshotsParams) bindSort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Sort = &raw + + if err := o.validateSort(formats); err != nil { + return err + } + + return nil +} + +// validateSort carries on validations for parameter Sort +func (o *GetFlagSnapshotsParams) validateSort(formats strfmt.Registry) error { + + if err := validate.EnumCase("sort", "query", *o.Sort, []interface{}{"ASC", "DESC"}, true); err != nil { + return err + } + + return nil +} diff --git a/swagger_gen/restapi/operations/flag/get_flag_snapshots_urlbuilder.go b/swagger_gen/restapi/operations/flag/get_flag_snapshots_urlbuilder.go index ba1a54f2..365acb75 100644 --- a/swagger_gen/restapi/operations/flag/get_flag_snapshots_urlbuilder.go +++ b/swagger_gen/restapi/operations/flag/get_flag_snapshots_urlbuilder.go @@ -20,6 +20,7 @@ type GetFlagSnapshotsURL struct { Limit *int64 Offset *int64 + Sort *string _basePath string // avoid unkeyed usage @@ -78,6 +79,14 @@ func (o *GetFlagSnapshotsURL) Build() (*url.URL, error) { qs.Set("offset", offsetQ) } + var sortQ string + if o.Sort != nil { + sortQ = *o.Sort + } + if sortQ != "" { + qs.Set("sort", sortQ) + } + _result.RawQuery = qs.Encode() return &_result, nil