Skip to content

Commit

Permalink
Merge pull request #549 from FelixTing/issue-545
Browse files Browse the repository at this point in the history
feat(notifications): Update Subscription DTO to adopt common Address
  • Loading branch information
lenny-goodell authored Mar 17, 2021
2 parents 36982f1 + 3e070a1 commit 954b5ff
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 135 deletions.
5 changes: 3 additions & 2 deletions v2/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ const (
// Constants for Address
const (
// Type
REST = "REST"
MQTT = "MQTT"
REST = "REST"
MQTT = "MQTT"
EMAIL = "EMAIL"
)

// Constants for DeviceProfile
Expand Down
30 changes: 27 additions & 3 deletions v2/dtos/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (
)

type Address struct {
Type string `json:"type" validate:"oneof='REST' 'MQTT'"`
Type string `json:"type" validate:"oneof='REST' 'MQTT' 'EMAIL'"`

Host string `json:"host" validate:"required"`
Port int `json:"port" validate:"required"`
Host string `json:"host" validate:"required_without=EmailAddresses"`
Port int `json:"port" validate:"required_without=EmailAddresses"`
EmailAddresses []string `json:"emailAddresses,omitempty" validate:"omitempty,gt=0,dive,email"`

RESTAddress `json:",inline" validate:"-"`
MQTTPubAddress `json:",inline" validate:"-"`
Expand Down Expand Up @@ -83,6 +84,13 @@ func NewMQTTAddress(host string, port int, publisher string, topic string) Addre
}
}

func NewEmailAddress(emailAddresses []string) Address {
return Address{
Type: v2.EMAIL,
EmailAddresses: emailAddresses,
}
}

func ToAddressModel(a Address) models.Address {
var address models.Address

Expand Down Expand Up @@ -144,3 +152,19 @@ func FromAddressModelToDTO(address models.Address) Address {
}
return dto
}

func ToAddressModels(dtos []Address) []models.Address {
models := make([]models.Address, len(dtos))
for i, c := range dtos {
models[i] = ToAddressModel(c)
}
return models
}

func FromAddressModelsToDTOs(models []models.Address) []Address {
dtos := make([]Address, len(models))
for i, c := range models {
dtos[i] = FromAddressModelToDTO(c)
}
return dtos
}
15 changes: 12 additions & 3 deletions v2/dtos/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
testHTTPMethod = "GET"
testPublisher = "testPublisher"
testTopic = "testTopic"
testEmail = "test@example.com"
)

var testRESTAddress = Address{
Expand All @@ -47,6 +48,8 @@ var testMQTTPubAddress = Address{
},
}

var testEmailAddress = NewEmailAddress([]string{testEmail})

func TestAddress_UnmarshalJSON(t *testing.T) {
restJsonStr := fmt.Sprintf(
`{"type":"%s","host":"%s","port":%d,"path":"%s","queryParameters":"%s","httpMethod":"%s"}`,
Expand All @@ -58,10 +61,8 @@ func TestAddress_UnmarshalJSON(t *testing.T) {
testMQTTPubAddress.Type, testMQTTPubAddress.Host, testMQTTPubAddress.Port,
testMQTTPubAddress.Publisher, testMQTTPubAddress.Topic,
)
emailJsonStr := fmt.Sprintf(`{"type":"%s","EmailAddresses":["%s"]}`, testEmailAddress.Type, testEmail)

type args struct {
data []byte
}
tests := []struct {
name string
expected Address
Expand All @@ -70,6 +71,7 @@ func TestAddress_UnmarshalJSON(t *testing.T) {
}{
{"unmarshal RESTAddress with success", testRESTAddress, []byte(restJsonStr), false},
{"unmarshal MQTTPubAddress with success", testMQTTPubAddress, []byte(mqttJsonStr), false},
{"unmarshal EmailAddress with success", testEmailAddress, []byte(emailJsonStr), false},
{"unmarshal invalid Address, empty data", Address{}, []byte{}, true},
{"unmarshal invalid Address, string data", Address{}, []byte("Invalid address"), true},
}
Expand Down Expand Up @@ -98,6 +100,11 @@ func TestAddress_Validate(t *testing.T) {
noMQTTPublisher.Publisher = ""
noMQTTTopic := testMQTTPubAddress
noMQTTTopic.Topic = ""

validEmail := testEmailAddress
invalidEmailAddress := testEmailAddress
invalidEmailAddress.EmailAddresses = []string{"test.example.com"}

tests := []struct {
name string
dto Address
Expand All @@ -108,6 +115,8 @@ func TestAddress_Validate(t *testing.T) {
{"valid MQTTPubAddress", validMQTT, false},
{"invalid MQTTPubAddress, no MQTT publisher", noMQTTPublisher, true},
{"invalid MQTTPubAddress, no MQTT Topic", noMQTTTopic, true},
{"valid EmailAddress", validEmail, false},
{"invalid EmailAddress", invalidEmailAddress, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
43 changes: 38 additions & 5 deletions v2/dtos/requests/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models"
)

var supportedChannelTypes = []string{v2.EMAIL, v2.REST}

// AddSubscriptionRequest defines the Request Content for POST Subscription DTO.
// This object and its properties correspond to the AddSubscriptionRequest object in the APIv2 specification:
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/support-notifications/2.x#/AddSubscriptionRequest
Expand All @@ -26,7 +28,18 @@ type AddSubscriptionRequest struct {
// Validate satisfies the Validator interface
func (request AddSubscriptionRequest) Validate() error {
err := v2.Validate(request)
return err
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
for _, c := range request.Subscription.Channels {
err = c.Validate()
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
} else if !contains(supportedChannelTypes, c.Type) {
return errors.NewCommonEdgeX(errors.KindContractInvalid, "MQTT is not valid type for Channel", nil)
}
}
return nil
}

// UnmarshalJSON implements the Unmarshaler interface for the AddSubscriptionRequest type
Expand All @@ -43,7 +56,7 @@ func (request *AddSubscriptionRequest) UnmarshalJSON(b []byte) error {

// validate AddSubscriptionRequest DTO
if err := request.Validate(); err != nil {
return err
return errors.NewCommonEdgeXWrapper(err)
}
return nil
}
Expand All @@ -68,7 +81,18 @@ type UpdateSubscriptionRequest struct {
// Validate satisfies the Validator interface
func (request UpdateSubscriptionRequest) Validate() error {
err := v2.Validate(request)
return err
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
}
for _, c := range request.Subscription.Channels {
err = c.Validate()
if err != nil {
return errors.NewCommonEdgeXWrapper(err)
} else if !contains(supportedChannelTypes, c.Type) {
return errors.NewCommonEdgeX(errors.KindContractInvalid, "MQTT is not valid type for Channel", nil)
}
}
return nil
}

// UnmarshalJSON implements the Unmarshaler interface for the UpdateSubscriptionRequest type
Expand All @@ -85,15 +109,15 @@ func (request *UpdateSubscriptionRequest) UnmarshalJSON(b []byte) error {

// validate UpdateSubscriptionRequest DTO
if err := request.Validate(); err != nil {
return err
return errors.NewCommonEdgeXWrapper(err)
}
return nil
}

// ReplaceSubscriptionModelFieldsWithDTO replace existing Subscription's fields with DTO patch
func ReplaceSubscriptionModelFieldsWithDTO(s *models.Subscription, patch dtos.UpdateSubscription) {
if patch.Channels != nil {
s.Channels = dtos.ToChannelModels(patch.Channels)
s.Channels = dtos.ToAddressModels(patch.Channels)
}
if patch.Categories != nil {
s.Categories = patch.Categories
Expand Down Expand Up @@ -128,3 +152,12 @@ func NewUpdateSubscriptionRequest(dto dtos.UpdateSubscription) UpdateSubscriptio
Subscription: dto,
}
}

func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}
return false
}
Loading

0 comments on commit 954b5ff

Please sign in to comment.