From 3832f4d3679b829c10df6856a944d2053a5f1358 Mon Sep 17 00:00:00 2001 From: Adrian Lapierre Date: Sat, 16 Oct 2021 14:01:34 +0200 Subject: [PATCH 1/3] new endpoints for config values --- .env | 2 +- cmd/dictionary-service/configuration.go | 14 +++++- configuration/repository.go | 10 +++++ configuration/service.go | 40 +++++++++++++++++ configuration/transport/http/doc.go | 12 +++++ configuration/transport/http/endpoints.go | 39 +++++++++++++--- swagger.yml | 40 ++++++++++++++++- testdata/configuration-test.http | 54 +++++++++++++++++++++++ types/json_date.go | 3 +- 9 files changed, 203 insertions(+), 11 deletions(-) diff --git a/.env b/.env index de83228..0bc9691 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -DICT_VERSION=0.0.22 +DICT_VERSION=0.0.23 diff --git a/cmd/dictionary-service/configuration.go b/cmd/dictionary-service/configuration.go index 0b3c240..0fccc71 100644 --- a/cmd/dictionary-service/configuration.go +++ b/cmd/dictionary-service/configuration.go @@ -10,9 +10,21 @@ import ( func makeConfigurationEndpoints(r *mux.Router, configurationService configuration.Service) { + // swagger:route POST /api/config/value addNewConfigEntry + // + // Create new config value in time for existing key + // Responses: + // 201: + // 400: RestError + r.Methods("POST", "OPTIONS").Path("/api/config/value").Handler(http.NewServer( + rest.MakeAddNewConfigurationEntryEndpoint(configurationService), + rest.DecodeAddNewConfigurationEntryRequest, + common.EncodeWithStatus(201), + )) + // swagger:route DELETE /api/config deleteConfigurationEntry // - // Save new config value + // Delete config value by key and date // Responses: // 204: // 400: RestError diff --git a/configuration/repository.go b/configuration/repository.go index d2d2213..c30bbde 100644 --- a/configuration/repository.go +++ b/configuration/repository.go @@ -22,6 +22,7 @@ type Repository interface { LoadValues(tenant, key string) ([]Configuration, error) Update(configuration *Configuration) error DeleteValue(tenant, key string, dateFrom time.Time) error + LoadFirst(key, tenant string) (*Configuration, error) } type configurationRepository struct { @@ -38,6 +39,15 @@ func (c *configurationRepository) LoadForDay(key, tenant string, day time.Time) return config, err } +func (c *configurationRepository) LoadFirst(key, tenant string) (*Configuration, error) { + + config := &Configuration{} + _, err := c.db.Query(config, `select * from dictionary.configuration where key = ? and tenant = ? order by date_from limit 1`, key, tenant) + + return config, err + +} + func (c *configurationRepository) Load(key, tenant string, from, to time.Time) ([]Configuration, error) { var result []Configuration diff --git a/configuration/service.go b/configuration/service.go index 2bff6b8..be240a0 100644 --- a/configuration/service.go +++ b/configuration/service.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "dictionaries-service/tenant" + "dictionaries-service/util" "fmt" slog "github.com/go-eden/slf4go" "time" @@ -27,6 +28,7 @@ type Service interface { LoadValues(ctx context.Context, key string) ([]Configuration, error) Update(configuration *Configuration) error DeleteValue(ctx context.Context, key string, dateFrom time.Time) error + AddNewValueInTime(ctx context.Context, key string, value *string, dateFrom, dateTo time.Time) error } func (c *service) LoadForDay(key, tenant string, day time.Time) (*Configuration, error) { @@ -81,6 +83,44 @@ func (c *service) Update(configuration *Configuration) error { return c.repository.Update(configuration) } +func (c *service) AddNewValueInTime(ctx context.Context, key string, value *string, dateFrom, dateTo time.Time) error { + + t, ok := tenant.FromContext(ctx) + if !ok { + return fmt.Errorf("can't read tenant from context") + } + + origin, err := c.repository.LoadFirst(key, t.Name) + + if err != nil { + slog.Warnf("can't read config entry for key = %s, %v", key, err) + return fmt.Errorf("there is no config entry for given key = %s", key) + } + + err = c.repository.Save(&Configuration{ + Key: key, + Tenant: t.Name, + Type: origin.Type, + Name: origin.Name, + Value: util.PointerToSqlNullString(value), + DateFrom: dateFrom, + DateTo: dateTo, + }) + if err != nil { + return err + } + + return nil +} + +func (c *service) UpdateValueInTime(key string, dateFrom time.Time, newValue string) { + +} + +func (c *service) UpdateDateTo(key string, dateFrom, newDateTo time.Time) { + +} + func (c *service) NewConfigValue(key, tenant, configType, name, value string) error { conf := &Configuration{ Key: key, diff --git a/configuration/transport/http/doc.go b/configuration/transport/http/doc.go index 0243e8a..5c0941b 100644 --- a/configuration/transport/http/doc.go +++ b/configuration/transport/http/doc.go @@ -2,6 +2,18 @@ package http import "dictionaries-service/configuration" +// swagger:parameters addNewConfigEntry +type addNewConfigurationEntryRequestWrapper struct { + + // optional tenant id + // in:header + Tenant string `json:"X-Tenant-ID"` + + // Configuration body + // in:body + Body addNewConfigurationEntryRequest +} + // swagger:parameters deleteConfigurationEntry //goland:noinspection GoUnusedType type deleteConfigurationEntryRequestWrapper struct { diff --git a/configuration/transport/http/endpoints.go b/configuration/transport/http/endpoints.go index 8074202..ee4ef26 100644 --- a/configuration/transport/http/endpoints.go +++ b/configuration/transport/http/endpoints.go @@ -52,16 +52,23 @@ type saveConfigurationRequest struct { DateTo types.JsonDate `json:"date_to"` } +type addNewConfigurationEntryRequest struct { + Key string `json:"key"` + Value *string `json:"value"` + DateFrom types.JsonDate `json:"date_from"` + DateTo types.JsonDate `json:"date_to"` +} + type deleteConfigurationRequest struct { Key string `json:"key"` DateFrom types.JsonDate `json:"date_from"` } type loadValueResponse struct { - Key string `json:"key"` - Value *string `json:"value"` - DateFrom time.Time `json:"date_from"` - DateTo time.Time `json:"date_to"` + Key string `json:"key"` + Value *string `json:"value"` + DateFrom types.JsonDate `json:"date_from"` + DateTo types.JsonDate `json:"date_to"` } type loadConfigurationResponse struct { @@ -70,6 +77,26 @@ type loadConfigurationResponse struct { Type string `json:"type"` } +func DecodeAddNewConfigurationEntryRequest(_ context.Context, r *http.Request) (interface{}, error) { + var request addNewConfigurationEntryRequest + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + return nil, err + } + return request, nil +} + +func MakeAddNewConfigurationEntryEndpoint(configurationService configuration.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + + req := request.(addNewConfigurationEntryRequest) + if err := configurationService.AddNewValueInTime(ctx, req.Key, req.Value, req.DateFrom.Time(), req.DateTo.Time()); err != nil { + return commons.MakeRestError(fmt.Errorf("can't create new in time entry for given key: %s, and date: %s", req.Key, req.DateFrom), + "cant_add_new_in_time_entry") + } + return nil, nil + } +} + func DecodeDeleteConfigurationRequest(_ context.Context, r *http.Request) (interface{}, error) { var request deleteConfigurationRequest if err := json.NewDecoder(r.Body).Decode(&request); err != nil { @@ -184,8 +211,8 @@ func MakeLoadValuesEndpoint(configurationService configuration.Service) endpoint res = append(res, loadValueResponse{ Key: v.Key, Value: util.SqlNullStringToStringPointer(v.Value), - DateFrom: v.DateFrom, - DateTo: v.DateTo, + DateFrom: types.JsonDate(v.DateFrom), + DateTo: types.JsonDate(v.DateTo), }) } diff --git a/swagger.yml b/swagger.yml index cc6a876..df30ca8 100644 --- a/swagger.yml +++ b/swagger.yml @@ -54,6 +54,24 @@ definitions: x-go-name: Type type: object x-go-package: dictionaries-service/configuration + addNewConfigurationEntryRequest: + properties: + date_from: + format: date + type: string + x-go-name: DateFrom + date_to: + format: date + type: string + x-go-name: DateTo + key: + type: string + x-go-name: Key + value: + type: string + x-go-name: Value + type: object + x-go-package: dictionaries-service/configuration/transport/http calendarResponse: properties: day: @@ -341,7 +359,7 @@ paths: $ref: '#/responses/RestError' /api/config: delete: - description: Save new config value + description: Delete config value by key and date operationId: deleteConfigurationEntry parameters: - description: optional tenant id @@ -452,6 +470,26 @@ paths: $ref: '#/responses/loadConfigurationOneResponseWrapper' "400": $ref: '#/responses/RestError' + /api/config/add: + post: + description: Create new config value in time for existing key + operationId: addNewConfigEntry + parameters: + - description: optional tenant id + in: header + name: X-Tenant-ID + type: string + x-go-name: Tenant + - description: Configuration body + in: body + name: Body + schema: + $ref: '#/definitions/addNewConfigurationEntryRequest' + responses: + "201": + description: "" + "400": + $ref: '#/responses/RestError' /api/configs/{day}: get: description: Loads all calendar items for given type and date range diff --git a/testdata/configuration-test.http b/testdata/configuration-test.http index e3bd2ae..0ae7a6f 100644 --- a/testdata/configuration-test.http +++ b/testdata/configuration-test.http @@ -39,6 +39,14 @@ Accept: application/json ### +GET http://localhost:9098/api/config/smtp.server +X-Tenant-ID: default +Accept-Language: en-EN +Cache-Control: no-cache +Accept: application/json + +### + POST http://localhost:9098/api/config X-Tenant-ID: default accept: application/json @@ -83,4 +91,50 @@ Content-Type: application/json "name": "nazwa", "type": "string", "value": "Ala ma kota 123" +} + +### + +POST http://localhost:9098/api/config +X-Tenant-ID: default +accept: application/json +Content-Type: application/json + +{ + "date_from": "2021-01-01", + "date_to": "2999-12-31", + "key": "smtp.server", + "name": "smtp Server Host Name", + "type": "string", + "value": "smtp.example.com" +} + +### + +POST http://localhost:9098/api/config +X-Tenant-ID: default +accept: application/json +Content-Type: application/json + +{ + "date_from": "2018-01-01", + "date_to": "2020-12-31", + "key": "smtp.server", + "name": "smtp Server Host Name", + "type": "string", + "value": "smtp-old.example.com" +} + +### + +POST http://localhost:9098/api/config/value +X-Tenant-ID: default +accept: application/json +Content-Type: application/json + +{ + "date_from": "2017-01-01", + "date_to": "2017-12-31", + "key": "smtp.server", + "value": "smtp-new.example.com" } \ No newline at end of file diff --git a/types/json_date.go b/types/json_date.go index f5a074f..c99c659 100644 --- a/types/json_date.go +++ b/types/json_date.go @@ -1,7 +1,6 @@ package types import ( - "encoding/json" "strings" "time" ) @@ -22,7 +21,7 @@ func (j *JsonDate) UnmarshalJSON(b []byte) error { } func (j JsonDate) MarshalJSON() ([]byte, error) { - return json.Marshal(j) + return []byte(j.String()), nil } // Format for printing your date From e094c3960d5dfd37bd10df24d26a4b5546115bf1 Mon Sep 17 00:00:00 2001 From: Adrian Lapierre Date: Sat, 16 Oct 2021 14:24:49 +0200 Subject: [PATCH 2/3] fix for date format in JsonDate type --- types/json_date.go | 2 +- types/json_date_test.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 types/json_date_test.go diff --git a/types/json_date.go b/types/json_date.go index c99c659..2345b6e 100644 --- a/types/json_date.go +++ b/types/json_date.go @@ -21,7 +21,7 @@ func (j *JsonDate) UnmarshalJSON(b []byte) error { } func (j JsonDate) MarshalJSON() ([]byte, error) { - return []byte(j.String()), nil + return []byte("\"" + j.String() + "\""), nil } // Format for printing your date diff --git a/types/json_date_test.go b/types/json_date_test.go new file mode 100644 index 0000000..58aba7d --- /dev/null +++ b/types/json_date_test.go @@ -0,0 +1,21 @@ +package types + +import ( + "encoding/json" + "fmt" + "testing" + "time" +) + +func TestJsonDate_Format(t *testing.T) { + + now := time.Now() + + marshal, err := json.Marshal(now) + if err != nil { + return + } + + fmt.Println(string(marshal)) + +} From c9290116d940daf4482fee9109de7da16e0b9266 Mon Sep 17 00:00:00 2001 From: Adrian Lapierre Date: Sat, 16 Oct 2021 16:57:12 +0200 Subject: [PATCH 3/3] refactoring for config endpoints - new structure of result from get all values endpoint - new endpoint to update value only - proper date format for GET endpoint --- cmd/dictionary-service/configuration.go | 22 +++-- configuration/repository.go | 16 ++++ configuration/service.go | 34 ++++++- configuration/transport/http/doc.go | 27 +++++- configuration/transport/http/endpoints.go | 103 ++++++++++++++++++---- swagger.yml | 94 +++++++++++++++----- testdata/configuration-test.http | 14 ++- transport/http/common.go | 2 +- util/util.go | 5 ++ 9 files changed, 271 insertions(+), 46 deletions(-) diff --git a/cmd/dictionary-service/configuration.go b/cmd/dictionary-service/configuration.go index 0fccc71..d8819e3 100644 --- a/cmd/dictionary-service/configuration.go +++ b/cmd/dictionary-service/configuration.go @@ -10,15 +10,27 @@ import ( func makeConfigurationEndpoints(r *mux.Router, configurationService configuration.Service) { - // swagger:route POST /api/config/value addNewConfigEntry + // swagger:route PUT /api/config/{key}/value/{from} updateConfigValue + // + // Create new config value in time for existing key + // Responses: + // 200: + // 400: RestError + r.Methods("PUT", "OPTIONS").Path("/api/config/{key}/value/{from}").Handler(http.NewServer( + rest.MakeUpdateValueInTimeEndpoint(configurationService), + rest.DecodeUpdateValueInTimeRequest, + common.EncodeWithStatus(200), + )) + + // swagger:route POST /api/config/{key}/value addNewConfigEntry // // Create new config value in time for existing key // Responses: // 201: // 400: RestError - r.Methods("POST", "OPTIONS").Path("/api/config/value").Handler(http.NewServer( - rest.MakeAddNewConfigurationEntryEndpoint(configurationService), - rest.DecodeAddNewConfigurationEntryRequest, + r.Methods("POST", "OPTIONS").Path("/api/config/{key}/value").Handler(http.NewServer( + rest.MakeAddNewConfigurationValueEndpoint(configurationService), + rest.DecodeAddNewConfigurationValueRequest, common.EncodeWithStatus(201), )) @@ -32,7 +44,7 @@ func makeConfigurationEndpoints(r *mux.Router, configurationService configuratio rest.MakeDeleteConfigurationValueEndpoint(configurationService), rest.DecodeDeleteConfigurationRequest, common.EncodeWithStatus(204), - )) + )) // todo: should be changed to DELETE /api/config/{key}/value/{from} // swagger:route PUT /api/config updateConfiguration // diff --git a/configuration/repository.go b/configuration/repository.go index c30bbde..553da9b 100644 --- a/configuration/repository.go +++ b/configuration/repository.go @@ -23,6 +23,7 @@ type Repository interface { Update(configuration *Configuration) error DeleteValue(tenant, key string, dateFrom time.Time) error LoadFirst(key, tenant string) (*Configuration, error) + LoadById(key, tenant string, from time.Time) (Configuration, error) } type configurationRepository struct { @@ -48,6 +49,21 @@ func (c *configurationRepository) LoadFirst(key, tenant string) (*Configuration, } +func (c *configurationRepository) LoadById(key, tenant string, from time.Time) (Configuration, error) { + + var result = Configuration{ + Key: key, + Tenant: tenant, + DateFrom: from, + } + + err := c.db.Model(&result). + WherePK(). + Select() + + return result, err +} + func (c *configurationRepository) Load(key, tenant string, from, to time.Time) ([]Configuration, error) { var result []Configuration diff --git a/configuration/service.go b/configuration/service.go index be240a0..189ab6e 100644 --- a/configuration/service.go +++ b/configuration/service.go @@ -29,6 +29,8 @@ type Service interface { Update(configuration *Configuration) error DeleteValue(ctx context.Context, key string, dateFrom time.Time) error AddNewValueInTime(ctx context.Context, key string, value *string, dateFrom, dateTo time.Time) error + UpdateValueInTime(ctx context.Context, key string, dateFrom time.Time, newValue *string) error + LoadEntry(ctx context.Context, key string) (*Configuration, error) } func (c *service) LoadForDay(key, tenant string, day time.Time) (*Configuration, error) { @@ -113,8 +115,38 @@ func (c *service) AddNewValueInTime(ctx context.Context, key string, value *stri return nil } -func (c *service) UpdateValueInTime(key string, dateFrom time.Time, newValue string) { +func (c *service) LoadEntry(ctx context.Context, key string) (*Configuration, error) { + t, ok := tenant.FromContext(ctx) + if !ok { + return nil, fmt.Errorf("can't read tenant from context") + } + + return c.repository.LoadFirst(key, t.Name) +} + +func (c *service) UpdateValueInTime(ctx context.Context, key string, dateFrom time.Time, newValue *string) error { + + t, ok := tenant.FromContext(ctx) + if !ok { + return fmt.Errorf("can't read tenant from context") + } + + origin, err := c.repository.LoadById(key, t.Name, dateFrom) + + if err != nil { + slog.Warnf("can't read config entry for key = %s, and date_from = %s, %v", key, dateFrom, err) + return fmt.Errorf("there is no config entry for given key = %s and date_from = %s", key, dateFrom) + } + + origin.Value = util.PointerToSqlNullString(newValue) + + err = c.repository.Update(&origin) + if err != nil { + slog.Warnf("can't update config value for key = %s, and date_from = %s, %v", key, dateFrom, err) + return err + } + return nil } func (c *service) UpdateDateTo(key string, dateFrom, newDateTo time.Time) { diff --git a/configuration/transport/http/doc.go b/configuration/transport/http/doc.go index 5c0941b..f06a49f 100644 --- a/configuration/transport/http/doc.go +++ b/configuration/transport/http/doc.go @@ -2,6 +2,26 @@ package http import "dictionaries-service/configuration" +// swagger:parameters updateConfigValue +type updateValueInTimeRequestWrapper struct { + + // optional tenant id + // in:header + Tenant string `json:"X-Tenant-ID"` + + // Config entry key + // in:path + Key string `json:"key"` + + // date from + // in:path + From string `json:"from"` + + // Configuration value + // in:body + Body updateValueInTimeRequest +} + // swagger:parameters addNewConfigEntry type addNewConfigurationEntryRequestWrapper struct { @@ -9,9 +29,12 @@ type addNewConfigurationEntryRequestWrapper struct { // in:header Tenant string `json:"X-Tenant-ID"` + // in:path + Key string `json:"key"` + // Configuration body // in:body - Body addNewConfigurationEntryRequest + Body addNewConfigurationValueRequest } // swagger:parameters deleteConfigurationEntry @@ -85,7 +108,7 @@ type loadShortResponseWrapper struct { type loadValuesResponseWrapper struct { // in:body - Body []loadValueResponse + Body loadValueResponseFull } // swagger:response loadConfigurationOneResponseWrapper diff --git a/configuration/transport/http/endpoints.go b/configuration/transport/http/endpoints.go index ee4ef26..a271124 100644 --- a/configuration/transport/http/endpoints.go +++ b/configuration/transport/http/endpoints.go @@ -9,6 +9,7 @@ import ( "dictionaries-service/util" "encoding/json" "fmt" + slog "github.com/go-eden/slf4go" "github.com/go-kit/kit/endpoint" "github.com/gorilla/mux" "net/http" @@ -52,20 +53,30 @@ type saveConfigurationRequest struct { DateTo types.JsonDate `json:"date_to"` } -type addNewConfigurationEntryRequest struct { - Key string `json:"key"` +type addNewConfigurationValueRequest struct { Value *string `json:"value"` DateFrom types.JsonDate `json:"date_from"` DateTo types.JsonDate `json:"date_to"` } +type addNewConfigurationValueCompleted struct { + Key string `json:"key"` + addNewConfigurationValueRequest +} + type deleteConfigurationRequest struct { Key string `json:"key"` DateFrom types.JsonDate `json:"date_from"` } -type loadValueResponse struct { - Key string `json:"key"` +type loadValueResponseFull struct { + Key string `json:"key"` + Type string `json:"type"` + Name string `json:"name"` + Values []valueInTime `json:"values"` +} + +type valueInTime struct { Value *string `json:"value"` DateFrom types.JsonDate `json:"date_from"` DateTo types.JsonDate `json:"date_to"` @@ -77,26 +88,79 @@ type loadConfigurationResponse struct { Type string `json:"type"` } -func DecodeAddNewConfigurationEntryRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request addNewConfigurationEntryRequest +type updateValueInTimeRequest struct { + Value *string `json:"value"` +} + +type updateValueInTimeCompleted struct { + key string + from time.Time + updateValueInTimeRequest +} + +func DecodeUpdateValueInTimeRequest(_ context.Context, r *http.Request) (interface{}, error) { + + var request updateValueInTimeRequest if err := json.NewDecoder(r.Body).Decode(&request); err != nil { return nil, err } - return request, nil + + vars := mux.Vars(r) + key := vars["key"] + from, err := util.StringToDate(vars["from"]) + + if err != nil { + slog.Errorf("can't convert %s into date", vars["from"]) + return nil, err + } + + return updateValueInTimeCompleted{ + key: key, + from: from, + updateValueInTimeRequest: request, + }, nil } -func MakeAddNewConfigurationEntryEndpoint(configurationService configuration.Service) endpoint.Endpoint { +func MakeUpdateValueInTimeEndpoint(configurationService configuration.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(addNewConfigurationEntryRequest) - if err := configurationService.AddNewValueInTime(ctx, req.Key, req.Value, req.DateFrom.Time(), req.DateTo.Time()); err != nil { - return commons.MakeRestError(fmt.Errorf("can't create new in time entry for given key: %s, and date: %s", req.Key, req.DateFrom), + req := request.(updateValueInTimeCompleted) + err := configurationService.UpdateValueInTime(ctx, req.key, req.from, req.Value) + if err != nil { + return commons.MakeRestError(fmt.Errorf("can't update in time value for given key: %s, and date: %s, %v", req.key, req.from, err), "cant_add_new_in_time_entry") } return nil, nil } } +func DecodeAddNewConfigurationValueRequest(_ context.Context, r *http.Request) (interface{}, error) { + var request addNewConfigurationValueRequest + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + return nil, err + } + + vars := mux.Vars(r) + key := vars["key"] + + return addNewConfigurationValueCompleted{ + Key: key, + addNewConfigurationValueRequest: request, + }, nil +} + +func MakeAddNewConfigurationValueEndpoint(configurationService configuration.Service) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + + req := request.(addNewConfigurationValueCompleted) + if err := configurationService.AddNewValueInTime(ctx, req.Key, req.Value, req.DateFrom.Time(), req.DateTo.Time()); err != nil { + return commons.MakeRestError(fmt.Errorf("can't create new in time value for given key: %s, and date: %s, %v", req.Key, req.DateFrom, err), + "cant_add_new_in_time_value") + } + return nil, nil + } +} + func DecodeDeleteConfigurationRequest(_ context.Context, r *http.Request) (interface{}, error) { var request deleteConfigurationRequest if err := json.NewDecoder(r.Body).Decode(&request); err != nil { @@ -200,23 +264,32 @@ func MakeLoadValuesEndpoint(configurationService configuration.Service) endpoint req := request.(valuesRequest) + entry, err := configurationService.LoadEntry(ctx, req.Key) + if err != nil { + return commons.MakeRestError(err, "cant_delete_dictionary_entry") + } + values, err := configurationService.LoadValues(ctx, req.Key) if err != nil { return commons.MakeRestError(err, "cant_delete_dictionary_entry") } - var res []loadValueResponse + var res []valueInTime for _, v := range values { - res = append(res, loadValueResponse{ - Key: v.Key, + res = append(res, valueInTime{ Value: util.SqlNullStringToStringPointer(v.Value), DateFrom: types.JsonDate(v.DateFrom), DateTo: types.JsonDate(v.DateTo), }) } - return res, nil + return &loadValueResponseFull{ + Key: entry.Key, + Type: entry.Type, + Name: entry.Name, + Values: res, + }, nil } } diff --git a/swagger.yml b/swagger.yml index df30ca8..07b1415 100644 --- a/swagger.yml +++ b/swagger.yml @@ -54,7 +54,7 @@ definitions: x-go-name: Type type: object x-go-package: dictionaries-service/configuration - addNewConfigurationEntryRequest: + addNewConfigurationValueRequest: properties: date_from: format: date @@ -64,9 +64,6 @@ definitions: format: date type: string x-go-name: DateTo - key: - type: string - x-go-name: Key value: type: string x-go-name: Value @@ -117,22 +114,22 @@ definitions: x-go-name: Value type: object x-go-package: dictionaries-service/configuration/transport/http - loadValueResponse: + loadValueResponseFull: properties: - date_from: - format: date-time - type: string - x-go-name: DateFrom - date_to: - format: date-time - type: string - x-go-name: DateTo key: type: string x-go-name: Key - value: + name: type: string - x-go-name: Value + x-go-name: Name + type: + type: string + x-go-name: Type + values: + items: + $ref: '#/definitions/valueInTime' + type: array + x-go-name: Values type: object x-go-package: dictionaries-service/configuration/transport/http saveConfigurationRequest: @@ -159,6 +156,28 @@ definitions: x-go-name: Value type: object x-go-package: dictionaries-service/configuration/transport/http + updateValueInTimeRequest: + properties: + value: + type: string + x-go-name: Value + type: object + x-go-package: dictionaries-service/configuration/transport/http + valueInTime: + properties: + date_from: + format: date + type: string + x-go-name: DateFrom + date_to: + format: date + type: string + x-go-name: DateTo + value: + type: string + x-go-name: Value + type: object + x-go-package: dictionaries-service/configuration/transport/http host: localhost:9098 info: description: |- @@ -470,7 +489,7 @@ paths: $ref: '#/responses/loadConfigurationOneResponseWrapper' "400": $ref: '#/responses/RestError' - /api/config/add: + /api/config/{key}/value: post: description: Create new config value in time for existing key operationId: addNewConfigEntry @@ -480,16 +499,53 @@ paths: name: X-Tenant-ID type: string x-go-name: Tenant + - in: path + name: key + required: true + type: string + x-go-name: Key - description: Configuration body in: body name: Body schema: - $ref: '#/definitions/addNewConfigurationEntryRequest' + $ref: '#/definitions/addNewConfigurationValueRequest' responses: "201": description: "" "400": $ref: '#/responses/RestError' + /api/config/{key}/value/{from}: + put: + description: Create new config value in time for existing key + operationId: updateConfigValue + parameters: + - description: optional tenant id + in: header + name: X-Tenant-ID + type: string + x-go-name: Tenant + - description: Config entry key + in: path + name: key + required: true + type: string + x-go-name: Key + - description: date from + in: path + name: from + required: true + type: string + x-go-name: From + - description: Configuration value + in: body + name: Body + schema: + $ref: '#/definitions/updateValueInTimeRequest' + responses: + "200": + description: "" + "400": + $ref: '#/responses/RestError' /api/configs/{day}: get: description: Loads all calendar items for given type and date range @@ -551,9 +607,7 @@ responses: loadValuesResponseWrapper: description: "" schema: - items: - $ref: '#/definitions/loadValueResponse' - type: array + $ref: '#/definitions/loadValueResponseFull' schemes: - http swagger: "2.0" diff --git a/testdata/configuration-test.http b/testdata/configuration-test.http index 0ae7a6f..db2d4c5 100644 --- a/testdata/configuration-test.http +++ b/testdata/configuration-test.http @@ -127,7 +127,7 @@ Content-Type: application/json ### -POST http://localhost:9098/api/config/value +POST http://localhost:9098/api/config/smtp.server/value X-Tenant-ID: default accept: application/json Content-Type: application/json @@ -135,6 +135,16 @@ Content-Type: application/json { "date_from": "2017-01-01", "date_to": "2017-12-31", - "key": "smtp.server", "value": "smtp-new.example.com" +} + +### + +PUT http://localhost:9098/api/config/smtp.server/value/2016-01-01 +X-Tenant-ID: default +accept: application/json +Content-Type: application/json + +{ + "value": "something else" } \ No newline at end of file diff --git a/transport/http/common.go b/transport/http/common.go index 98c0a5b..9c3cecd 100644 --- a/transport/http/common.go +++ b/transport/http/common.go @@ -84,7 +84,7 @@ func MakeRestError(err error, message string) (interface{}, error) { return &RestError{ Error: message, ErrorDescription: err.Error(), - }, nil + }, err } func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { diff --git a/util/util.go b/util/util.go index af5e427..757eeb3 100644 --- a/util/util.go +++ b/util/util.go @@ -67,3 +67,8 @@ func StringToTime(str string) (time.Time, error) { layout := "2006-01-02T15:04:05.000Z" return time.Parse(layout, str) } + +func StringToDate(str string) (time.Time, error) { + layout := "2006-01-02" + return time.Parse(layout, str) +}