Skip to content

Commit

Permalink
added get subscription attributes
Browse files Browse the repository at this point in the history
rename

review ref

review ref
  • Loading branch information
Dai.Otsuka authored and Admiral-Piett committed Sep 20, 2024
1 parent bacb1d3 commit f06f3d7
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 156 deletions.
69 changes: 69 additions & 0 deletions app/gosns/get_subscription_attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package gosns

import (
"encoding/json"
"net/http"
"strconv"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/interfaces"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/utils"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
)

func GetSubscriptionAttributesV1(req *http.Request) (int, interfaces.AbstractResponseBody) {

requestBody := models.NewGetSubscriptionAttributesRequest()
ok := utils.REQUEST_TRANSFORMER(requestBody, req, false)

if !ok {
log.Error("Invalid Request - GetSubscriptionAttributesV1")
return utils.CreateErrorResponseV1("InvalidParameterValue", false)
}

subscriptionArn := requestBody.SubscriptionArn

for _, topic := range app.SyncTopics.Topics {
for _, sub := range topic.Subscriptions {
if sub.SubscriptionArn == subscriptionArn {

entries := make([]models.SubscriptionAttributeEntry, 0, 0)
entry := models.SubscriptionAttributeEntry{Key: "Owner", Value: app.CurrentEnvironment.AccountID}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "RawMessageDelivery", Value: strconv.FormatBool(sub.Raw)}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "TopicArn", Value: sub.TopicArn}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "Endpoint", Value: sub.EndPoint}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "PendingConfirmation", Value: "false"}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "ConfirmationWasAuthenticated", Value: "true"}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "SubscriptionArn", Value: sub.SubscriptionArn}
entries = append(entries, entry)
entry = models.SubscriptionAttributeEntry{Key: "Protocol", Value: sub.Protocol}
entries = append(entries, entry)

if sub.FilterPolicy != nil {
filterPolicyBytes, _ := json.Marshal(sub.FilterPolicy)
entry = models.SubscriptionAttributeEntry{Key: "FilterPolicy", Value: string(filterPolicyBytes)}
entries = append(entries, entry)
}

result := models.GetSubscriptionAttributesResult{Attributes: models.GetSubscriptionAttributes{Entries: entries}}
uuid := uuid.NewString()
respStruct := models.GetSubscriptionAttributesResponse{
Xmlns: models.BASE_XMLNS,
Result: result,
Metadata: app.ResponseMetadata{RequestId: uuid}}

return http.StatusOK, respStruct

}
}
}
return utils.CreateErrorResponseV1("SubscriptionNotFound", false)
}
121 changes: 121 additions & 0 deletions app/gosns/get_subscription_attributes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package gosns

import (
"net/http"
"testing"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/conf"
"github.com/Admiral-Piett/goaws/app/interfaces"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/test"
"github.com/Admiral-Piett/goaws/app/utils"
"github.com/stretchr/testify/assert"
)

func TestGetSubscriptionAttributesV1_NonExistentSubscription(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "NoQueuesOrTopics")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
v := resultingStruct.(*models.GetSubscriptionAttributesRequest)
*v = models.GetSubscriptionAttributesRequest{
SubscriptionArn: "hogehoge",
}
return true
}

_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetSubscriptionAttributesV1(r)
errorResult := response.GetResult().(models.ErrorResult)

expected := models.ErrorResult{
Type: "Not Found",
Code: "AWS.SimpleNotificationService.NonExistentSubscription",
Message: "The specified subscription does not exist for this wsdl version.",
}
assert.Equal(t, http.StatusNotFound, code)
assert.Equal(t, expected, errorResult)
}

func TestGetSubscriptionAttributesV1_TransformError(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "Local")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
return false
}

_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, _ := GetSubscriptionAttributesV1(r)

assert.Equal(t, http.StatusBadRequest, code)
}

func TestGetSubscriptionAttributesV1_success(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "Local")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

localTopic1 := app.SyncTopics.Topics["local-topic1"]
subscriptions := localTopic1.Subscriptions
utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
v := resultingStruct.(*models.GetSubscriptionAttributesRequest)
*v = models.GetSubscriptionAttributesRequest{
// local-queue5
SubscriptionArn: subscriptions[1].SubscriptionArn,
}
return true
}
_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetSubscriptionAttributesV1(r)

result := response.GetResult().(models.GetSubscriptionAttributesResult)
assert.Equal(t, http.StatusOK, code)
expectedAttributes := []models.SubscriptionAttributeEntry{
{
Key: "Owner",
Value: app.CurrentEnvironment.AccountID,
},
{
Key: "RawMessageDelivery",
Value: "true",
},
{
Key: "TopicArn",
Value: localTopic1.Arn,
},
{
Key: "Endpoint",
Value: subscriptions[1].EndPoint,
},
{
Key: "PendingConfirmation",
Value: "false",
},
{
Key: "ConfirmationWasAuthenticated",
Value: "true",
}, {
Key: "SubscriptionArn",
Value: subscriptions[1].SubscriptionArn,
}, {
Key: "Protocol",
Value: "sqs",
},
{
Key: "FilterPolicy",
Value: "{\"foo\":[\"bar\"]}",
},
}

assert.ElementsMatch(t, expectedAttributes, result.Attributes.Entries)
}
49 changes: 0 additions & 49 deletions app/gosns/gosns.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -220,54 +219,6 @@ func SetSubscriptionAttributes(w http.ResponseWriter, req *http.Request) {
createErrorResponse(w, req, "SubscriptionNotFound")
}

func GetSubscriptionAttributes(w http.ResponseWriter, req *http.Request) {

content := req.FormValue("ContentType")
subsArn := req.FormValue("SubscriptionArn")

for _, topic := range app.SyncTopics.Topics {
for _, sub := range topic.Subscriptions {
if sub.SubscriptionArn == subsArn {

entries := make([]app.SubscriptionAttributeEntry, 0, 0)
entry := app.SubscriptionAttributeEntry{Key: "Owner", Value: app.CurrentEnvironment.AccountID}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "RawMessageDelivery", Value: strconv.FormatBool(sub.Raw)}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "TopicArn", Value: sub.TopicArn}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "Endpoint", Value: sub.EndPoint}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "PendingConfirmation", Value: "false"}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "ConfirmationWasAuthenticated", Value: "true"}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "SubscriptionArn", Value: sub.SubscriptionArn}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "Protocol", Value: sub.Protocol}
entries = append(entries, entry)
entry = app.SubscriptionAttributeEntry{Key: "Endpoint", Value: sub.EndPoint}
entries = append(entries, entry)

if sub.FilterPolicy != nil {
filterPolicyBytes, _ := json.Marshal(sub.FilterPolicy)
entry = app.SubscriptionAttributeEntry{Key: "FilterPolicy", Value: string(filterPolicyBytes)}
entries = append(entries, entry)
}

result := app.GetSubscriptionAttributesResult{SubscriptionAttributes: app.SubscriptionAttributes{Entries: entries}}
uuid, _ := common.NewUUID()
respStruct := app.GetSubscriptionAttributesResponse{"http://sns.amazonaws.com/doc/2010-03-31", result, app.ResponseMetadata{RequestId: uuid}}

SendResponseBack(w, req, respStruct, content)

return
}
}
}
createErrorResponse(w, req, "SubscriptionNotFound")
}

// NOTE: The use case for this is to use GoAWS to call some external system with the message payload. Essentially
// it is a localized subscription to some non-AWS endpoint.
func callEndpoint(endpoint string, subArn string, msg app.SNSMessage, raw bool) error {
Expand Down
68 changes: 0 additions & 68 deletions app/gosns/gosns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,74 +74,6 @@ func TestListSubscriptionByTopicResponse_No_Owner(t *testing.T) {
}
}

func TestGetSubscriptionAttributesHandler_POST_Success(t *testing.T) {
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Fatal(err)
}

defer func() {
test.ResetApp()
}()

topicName := "testing"
topicArn := "arn:aws:sns:" + app.CurrentEnvironment.Region + ":000000000000:" + topicName
subArn, _ := common.NewUUID()
subArn = topicArn + ":" + subArn
app.SyncTopics.Topics[topicName] = &app.Topic{Name: topicName, Arn: topicArn, Subscriptions: []*app.Subscription{
{
SubscriptionArn: subArn,
FilterPolicy: &app.FilterPolicy{
"foo": {"bar"},
},
},
}}

form := url.Values{}
form.Add("SubscriptionArn", subArn)
req.PostForm = form

// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
rr := httptest.NewRecorder()
handler := http.HandlerFunc(GetSubscriptionAttributes)

// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
// directly and pass in our Request and ResponseRecorder.
handler.ServeHTTP(rr, req)

// Check the status code is what we expect.
if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}

// Check the response body is what we expect.
expected := "</GetSubscriptionAttributesResult>"
if !strings.Contains(rr.Body.String(), expected) {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}

expectedElements := []string{"Owner", "RawMessageDelivery", "TopicArn", "Endpoint", "PendingConfirmation",
"ConfirmationWasAuthenticated", "SubscriptionArn", "Protocol", "FilterPolicy"}
for _, element := range expectedElements {
expected := "<key>" + element + "</key>"
if !strings.Contains(rr.Body.String(), expected) {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}
}

// Check the response body is what we expect.
expected = "{&#34;foo&#34;:[&#34;bar&#34;]}"
if !strings.Contains(rr.Body.String(), expected) {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}
}

func TestSetSubscriptionAttributesHandler_FilterPolicy_POST_Success(t *testing.T) {
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
Expand Down
2 changes: 1 addition & 1 deletion app/gosns/unsubscribe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@ func TestUnsubscribeV1_invalid_subscription_arn(t *testing.T) {
_, r := test.GenerateRequestInfo("POST", "/", nil, true)
status, _ := UnsubscribeV1(r)

assert.Equal(t, http.StatusBadRequest, status)
assert.Equal(t, http.StatusNotFound, status)
}
2 changes: 1 addition & 1 deletion app/models/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func init() {
SnsErrors = map[string]SnsErrorType{
"InvalidParameterValue": {HttpError: http.StatusBadRequest, Type: "InvalidParameterValue", Code: "AWS.SimpleNotificationService.InvalidParameterValue", Message: "An invalid or out-of-range value was supplied for the input parameter."},
"TopicNotFound": {HttpError: http.StatusBadRequest, Type: "Not Found", Code: "AWS.SimpleNotificationService.NonExistentTopic", Message: "The specified topic does not exist for this wsdl version."},
"SubscriptionNotFound": {HttpError: http.StatusBadRequest, Type: "Not Found", Code: "AWS.SimpleNotificationService.NonExistentSubscription", Message: "The specified subscription does not exist for this wsdl version."},
"SubscriptionNotFound": {HttpError: http.StatusNotFound, Type: "Not Found", Code: "AWS.SimpleNotificationService.NonExistentSubscription", Message: "The specified subscription does not exist for this wsdl version."},
"TopicExists": {HttpError: http.StatusBadRequest, Type: "Duplicate", Code: "AWS.SimpleNotificationService.TopicAlreadyExists", Message: "The specified topic already exists."},
"ValidationError": {HttpError: http.StatusBadRequest, Type: "InvalidParameter", Code: "AWS.SimpleNotificationService.ValidationError", Message: "The input fails to satisfy the constraints specified by an AWS service."},
}
Expand Down
29 changes: 29 additions & 0 deletions app/models/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,32 @@ func (r ListSubscriptionsResponse) GetResult() interface{} {
func (r ListSubscriptionsResponse) GetRequestId() string {
return r.Metadata.RequestId
}

/*** Get Subscription Attributes ***/
type GetSubscriptionAttributesResult struct {
Attributes GetSubscriptionAttributes `xml:"Attributes,omitempty"`
}

type GetSubscriptionAttributes struct {
/* SubscriptionArn, FilterPolicy */
Entries []SubscriptionAttributeEntry `xml:"entry,omitempty"`
}

type SubscriptionAttributeEntry struct {
Key string `xml:"key,omitempty"`
Value string `xml:"value,omitempty"`
}

type GetSubscriptionAttributesResponse struct {
Xmlns string `xml:"xmlns,attr,omitempty"`
Result GetSubscriptionAttributesResult `xml:"GetSubscriptionAttributesResult"`
Metadata app.ResponseMetadata `xml:"ResponseMetadata,omitempty"`
}

func (r GetSubscriptionAttributesResponse) GetResult() interface{} {
return r.Result
}

func (r GetSubscriptionAttributesResponse) GetRequestId() string {
return r.Metadata.RequestId
}
11 changes: 11 additions & 0 deletions app/models/sns.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,14 @@ type ListSubscriptionsRequest struct {
}

func (r *ListSubscriptionsRequest) SetAttributesFromForm(values url.Values) {}

// Get Subscription Attributes V1
func NewGetSubscriptionAttributesRequest() *GetSubscriptionAttributesRequest {
return &GetSubscriptionAttributesRequest{}
}

type GetSubscriptionAttributesRequest struct {
SubscriptionArn string `json:"SubscriptionArn" schema:"SubscriptionArn"`
}

func (r *GetSubscriptionAttributesRequest) SetAttributesFromForm(values url.Values) {}
Loading

0 comments on commit f06f3d7

Please sign in to comment.