diff --git a/broker/client/client.go b/broker/client/client.go
index cd9e08b4..62ecc582 100644
--- a/broker/client/client.go
+++ b/broker/client/client.go
@@ -31,8 +31,7 @@ const KindConfirmationError = "confirmation-error"
const BrokerInfoStatus = iso18626.TypeStatusExpectToSupply
-// TODO this must be removed and saved from the initial request
-var BrokerSymbol = utils.GetEnv("BROKER_SYMBOL", "ISIL:BROKER")
+var brokerSymbol = utils.GetEnv("BROKER_SYMBOL", "ISIL:BROKER")
var appendSupplierInfo, _ = utils.GetEnvBool("SUPPLIER_INFO", true)
var appendRequestingAgencyInfo, _ = utils.GetEnvBool("REQ_AGENCY_INFO", true)
var appendReturnInfo, _ = utils.GetEnvBool("RETURN_INFO", true)
@@ -486,14 +485,14 @@ func (c *Iso18626Client) getSelectedSupplierAndPeer(ctx extctx.ExtendedContext,
}
func (c *Iso18626Client) createMessageHeader(transaction ill_db.IllTransaction, sup *ill_db.LocatedSupplier, isRequestingMessage bool, brokerMode string) iso18626.Header {
- requesterSymbol := strings.SplitN(BrokerSymbol, ":", 2)
+ requesterSymbol := strings.SplitN(brokerSymbol, ":", 2)
if !isRequestingMessage || brokerMode == string(extctx.BrokerModeTransparent) {
requesterSymbol = strings.SplitN(transaction.RequesterSymbol.String, ":", 2)
}
if len(requesterSymbol) < 2 {
requesterSymbol = append(requesterSymbol, "")
}
- supplierSymbol := strings.SplitN(BrokerSymbol, ":", 2)
+ supplierSymbol := strings.SplitN(brokerSymbol, ":", 2)
if sup != nil && sup.SupplierSymbol != "" && (isRequestingMessage || brokerMode == string(extctx.BrokerModeTransparent)) {
supplierSymbol = strings.SplitN(sup.SupplierSymbol, ":", 2)
}
diff --git a/broker/handler/iso18626-handler.go b/broker/handler/iso18626-handler.go
index 46c2137a..0cc95dda 100644
--- a/broker/handler/iso18626-handler.go
+++ b/broker/handler/iso18626-handler.go
@@ -25,23 +25,24 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)
+var brokerSymbol = utils.GetEnv("BROKER_SYMBOL", "ISIL:BROKER")
+
const HANDLER_COMP = "iso18626_handler"
type ErrorValue string
const (
- ReqIdAlreadyExists ErrorValue = "requestingAgencyRequestId: request with a given ID already exists"
- ReqIdIsEmpty ErrorValue = "requestingAgencyRequestId: cannot be empty"
- ReqIdNotFound ErrorValue = "requestingAgencyRequestId: request with a given ID not found"
- RetryNotPossible ErrorValue = "requestType: Retry not possible"
- SupplierNotFound ErrorValue = "supplyingAgencyId: located supplier cannot be found"
- IncorrectSupplier ErrorValue = "supplyingAgencyId: not a selected supplier for this request"
- UnsupportedRequestType ErrorValue = "requestType: unsupported value"
- ReqAgencyNotFound ErrorValue = "requestingAgencyId: requesting agency not found"
- CouldNotSendReqToPeer ErrorValue = "Could not send request to peer"
- InvalidAction ErrorValue = "%v is not a valid action"
- InvalidStatus ErrorValue = "%v is not a valid status"
- InvalidReason ErrorValue = "%v is not a valid reason"
+ ReqIdAlreadyExists ErrorValue = "requestingAgencyRequestId: request with a given ID already exists"
+ ReqIdIsEmpty ErrorValue = "requestingAgencyRequestId: cannot be empty"
+ ReqIdNotFound ErrorValue = "requestingAgencyRequestId: request with a given ID not found"
+ RetryNotPossible ErrorValue = "requestType: Retry not possible"
+ SupplierNotFoundOrInvalid ErrorValue = "supplyingAgencyId: supplying agency not found or invalid"
+ UnsupportedRequestType ErrorValue = "requestType: unsupported value"
+ ReqAgencyNotFound ErrorValue = "requestingAgencyId: requesting agency not found"
+ CouldNotSendReqToPeer ErrorValue = "Could not send request to peer"
+ InvalidAction ErrorValue = "%v is not a valid action"
+ InvalidStatus ErrorValue = "%v is not a valid status"
+ InvalidReason ErrorValue = "%v is not a valid reason"
)
const PublicFailedToProcessReqMsg = "failed to process request"
@@ -333,25 +334,41 @@ func handleRequestingAgencyMessage(ctx extctx.ExtendedContext, illMessage *iso18
handleRequestingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, ReqIdIsEmpty)
return
}
-
+ symbol := getSupplierSymbol(&illMessage.RequestingAgencyMessage.Header)
+ if len(symbol) == 0 {
+ handleRequestingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFoundOrInvalid)
+ return
+ }
eventData := events.EventData{
CommonEventData: events.CommonEventData{
IncomingMessage: illMessage,
},
}
-
var err error
var illTrans ill_db.IllTransaction
var action iso18626.TypeAction
+ errorValue := ReqIdNotFound
err = repo.WithTxFunc(ctx, func(repo ill_db.IllRepo) error {
illTrans, err = repo.GetIllTransactionByRequesterRequestIdForUpdate(ctx, createPgText(requestingRequestId))
if err != nil {
+ errorValue = ReqIdNotFound
return err
}
action = validateAction(ctx, illMessage, w, eventData, eventBus, illTrans)
if action == "" {
return nil
}
+ if symbol != brokerSymbol {
+ supp, err := repo.GetSelectedSupplierForIllTransaction(ctx, illTrans.ID)
+ if err != nil {
+ errorValue = SupplierNotFoundOrInvalid
+ return err
+ }
+ if supp.SupplierSymbol != symbol {
+ errorValue = SupplierNotFoundOrInvalid
+ return pgx.ErrNoRows
+ }
+ }
illTrans.PrevRequesterAction = illTrans.LastRequesterAction
illTrans.LastRequesterAction = createPgText(string(action))
_, err = repo.SaveIllTransaction(ctx, ill_db.SaveIllTransactionParams(illTrans))
@@ -359,7 +376,7 @@ func handleRequestingAgencyMessage(ctx extctx.ExtendedContext, illMessage *iso18
})
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
- handleRequestingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, ReqIdNotFound)
+ handleRequestingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, errorValue)
return
}
ctx.Logger().Error(InternalFailedToSaveTx, "error", err)
@@ -383,6 +400,14 @@ func handleRequestingAgencyMessage(ctx extctx.ExtendedContext, illMessage *iso18
wg.Wait()
}
+func getSupplierSymbol(header *iso18626.Header) string {
+ if len(header.SupplyingAgencyId.AgencyIdType.Text) == 0 || len(header.SupplyingAgencyId.AgencyIdValue) == 0 {
+ return ""
+ }
+ return header.SupplyingAgencyId.AgencyIdType.Text + ":" +
+ header.SupplyingAgencyId.AgencyIdValue
+}
+
func validateAction(ctx extctx.ExtendedContext, illMessage *iso18626.ISO18626Message, w http.ResponseWriter, eventData events.EventData, eventBus events.EventBus, illTrans ill_db.IllTransaction) iso18626.TypeAction {
action, ok := iso18626.ActionMap[string(illMessage.RequestingAgencyMessage.Action)]
if !ok {
@@ -435,10 +460,9 @@ func handleSupplyingAgencyMessage(ctx extctx.ExtendedContext, illMessage *iso186
http.Error(w, PublicFailedToProcessReqMsg, http.StatusInternalServerError)
return
}
- symbol := illMessage.SupplyingAgencyMessage.Header.SupplyingAgencyId.AgencyIdType.Text + ":" +
- illMessage.SupplyingAgencyMessage.Header.SupplyingAgencyId.AgencyIdValue
- if len(symbol) < 3 {
- handleSupplyingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, IncorrectSupplier)
+ symbol := getSupplierSymbol(&illMessage.SupplyingAgencyMessage.Header)
+ if len(symbol) == 0 {
+ handleSupplyingAgencyError(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFoundOrInvalid)
return
}
requester, err := repo.GetPeerById(ctx, illTrans.RequesterID.String)
@@ -468,18 +492,18 @@ func handleSupplyingAgencyMessage(ctx extctx.ExtendedContext, illMessage *iso186
return
}
if supplier.SupplierStatus != ill_db.SupplierStateSkippedPg {
- handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFound,
+ handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFoundOrInvalid,
eventBus, illTrans.ID)
return
}
} else {
- handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, IncorrectSupplier,
+ handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFoundOrInvalid,
eventBus, illTrans.ID)
return
}
}
if supplier.SupplierSymbol != symbol { //ensure we found the correct supplier
- handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, IncorrectSupplier,
+ handleSupplyingAgencyErrorWithNotice(ctx, w, illMessage, iso18626.TypeErrorTypeUnrecognisedDataValue, SupplierNotFoundOrInvalid,
eventBus, illTrans.ID)
return
}
diff --git a/broker/handler/iso18626-handler_test.go b/broker/handler/iso18626-handler_test.go
new file mode 100644
index 00000000..19b73b51
--- /dev/null
+++ b/broker/handler/iso18626-handler_test.go
@@ -0,0 +1,28 @@
+package handler
+
+import (
+ "testing"
+
+ "github.com/indexdata/crosslink/iso18626"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetSupplierSymbol(t *testing.T) {
+ header := &iso18626.Header{
+ SupplyingAgencyId: iso18626.TypeAgencyId{
+ AgencyIdType: iso18626.TypeSchemeValuePair{
+ Text: "ISIL",
+ },
+ AgencyIdValue: "12345",
+ },
+ }
+ symbol := getSupplierSymbol(header)
+ assert.Equal(t, "ISIL:12345", symbol)
+ header.SupplyingAgencyId.AgencyIdType.Text = ""
+ symbol = getSupplierSymbol(header)
+ assert.Equal(t, "", symbol)
+ header.SupplyingAgencyId.AgencyIdType.Text = "ISIL"
+ header.SupplyingAgencyId.AgencyIdValue = ""
+ symbol = getSupplierSymbol(header)
+ assert.Equal(t, "", symbol)
+}
diff --git a/broker/test/handler/iso18626-handler_test.go b/broker/test/handler/iso18626-handler_test.go
index c454d754..2f344c65 100644
--- a/broker/test/handler/iso18626-handler_test.go
+++ b/broker/test/handler/iso18626-handler_test.go
@@ -230,7 +230,7 @@ func TestIso18626PostSupplyingMessageIncorrectSupplier(t *testing.T) {
assert.Equal(t, http.StatusOK, rr.Code)
msgError := "ERROR"
assert.Contains(t, rr.Body.String(), msgError)
- errorValue := "supplyingAgencyId: not a selected supplier for this request"
+ errorValue := "supplyingAgencyId: supplying agency not found or invalid"
assert.Contains(t, rr.Body.String(), errorValue)
}
@@ -288,11 +288,13 @@ func TestIso18626PostSupplyingMessageReqNotFound(t *testing.T) {
func TestIso18626PostRequestingMessage(t *testing.T) {
tests := []struct {
- name string
- status int
- contains string
- urlEnding string
- useMock bool
+ name string
+ status int
+ contains string
+ urlEnding string
+ supplierSymbol string
+ skipped bool
+ useMock bool
}{
{
name: "ResponseSuccessful",
@@ -322,35 +324,61 @@ func TestIso18626PostRequestingMessage(t *testing.T) {
urlEnding: "/notExists",
useMock: false,
},
+ {
+ name: "ResponseSupplierNotFoundOrInvalid-WrongSymbol",
+ status: 200,
+ contains: "supplyingAgencyId: supplying agency not found or invalid",
+ urlEnding: "",
+ supplierSymbol: "ISIL:SLNP_TWO_B",
+ useMock: true,
+ },
+ {
+ name: "ResponseSupplierNotFoundOrInvalid-Skipped",
+ status: 200,
+ contains: "supplyingAgencyId: supplying agency not found or invalid",
+ urlEnding: "",
+ supplierSymbol: "ISIL:SLNP_TWO_A",
+ skipped: true,
+ useMock: true,
+ },
}
appCtx := extctx.CreateExtCtxWithArgs(context.Background(), nil)
- data, _ := os.ReadFile("../testdata/reqmsg-ok.xml")
+ data, _ := os.ReadFile("../testdata/reqmsg-notification.xml")
illId := uuid.NewString()
- requester := apptest.CreatePeer(t, illRepo, "isil:requester1", adapter.MOCK_CLIENT_URL)
+ requester := apptest.CreatePeer(t, illRepo, "ISIL:SLNP_ONE", adapter.MOCK_CLIENT_URL)
_, err := illRepo.SaveIllTransaction(appCtx, ill_db.SaveIllTransactionParams{
ID: illId,
Timestamp: test.GetNow(),
RequesterRequestID: apptest.CreatePgText("reqid"),
- RequesterSymbol: apptest.CreatePgText("isil:requester1"),
+ RequesterSymbol: apptest.CreatePgText("ISIL:SLNP_ONE"),
RequesterID: apptest.CreatePgText(requester.ID),
})
if err != nil {
t.Errorf("failed to create ill transaction: %s", err)
}
- peer := apptest.CreatePeer(t, illRepo, "isil:reqTest", adapter.MOCK_CLIENT_URL)
- apptest.CreateLocatedSupplier(t, illRepo, illId, peer.ID, "isil:reqTest", "selected")
-
+ supplier := apptest.CreatePeer(t, illRepo, "ISIL:SLNP_TWO_A", adapter.MOCK_CLIENT_URL)
+ locSup := apptest.CreateLocatedSupplier(t, illRepo, illId, supplier.ID, "ISIL:SLNP_TWO_A", "selected")
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.useMock {
- peer.Url = adapter.MOCK_CLIENT_URL + tt.urlEnding
+ supplier.Url = adapter.MOCK_CLIENT_URL + tt.urlEnding
} else {
port, _ := test.GetFreePort()
- peer.Url = "http:localhost:" + strconv.Itoa(port) + tt.urlEnding
+ supplier.Url = "http:localhost:" + strconv.Itoa(port) + tt.urlEnding
+ }
+ supplier, err = illRepo.SavePeer(appCtx, ill_db.SavePeerParams(supplier))
+ if err != nil {
+ t.Errorf("failed to update supplier peer : %s", err)
+ }
+ if tt.supplierSymbol != "" {
+ locSup.SupplierSymbol = tt.supplierSymbol
+ }
+ if tt.skipped {
+ locSup.SupplierStatus = ill_db.SupplierStateSkippedPg
}
- peer, err = illRepo.SavePeer(appCtx, ill_db.SavePeerParams(peer))
+ _, err := illRepo.SaveLocatedSupplier(appCtx, ill_db.SaveLocatedSupplierParams(locSup))
if err != nil {
- t.Errorf("failed to update peer : %s", err)
+ t.Errorf("failed to update located supplier : %s", err)
}
url := "http://localhost:" + strconv.Itoa(app.HTTP_PORT) + "/iso18626"
req, _ := http.NewRequest("POST", url, bytes.NewReader(data))
diff --git a/broker/test/testdata/reqmsg-notification.xml b/broker/test/testdata/reqmsg-notification.xml
new file mode 100644
index 00000000..9c89ddf3
--- /dev/null
+++ b/broker/test/testdata/reqmsg-notification.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ ISIL
+ SLNP_TWO_A
+
+
+ ISIL
+ SLNP_ONE
+
+
+ 2024-12-12T20:12:00.62959771Z
+ reqid
+ c488bef0-5735-4c33-ba13-a9f343447574
+
+ Notification
+
+