diff --git a/nip47/controllers/get_budget_controller.go b/nip47/controllers/get_budget_controller.go index ccf0c4d3..818546fd 100644 --- a/nip47/controllers/get_budget_controller.go +++ b/nip47/controllers/get_budget_controller.go @@ -2,10 +2,13 @@ package controllers import ( "context" + "errors" "github.com/getAlby/go-nostr" "github.com/getAlby/hub/db/queries" + "gorm.io/gorm" + "github.com/getAlby/hub/constants" "github.com/getAlby/hub/db" "github.com/getAlby/hub/logger" "github.com/getAlby/hub/nip47/models" @@ -26,8 +29,21 @@ func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip }).Debug("Getting budget") appPermission := db.AppPermission{} - controller.db.Where("app_id = ? AND scope = ?", app.ID, models.PAY_INVOICE_METHOD).First(&appPermission) + result := controller.db.Where("app_id = ? AND scope = ?", app.ID, constants.PAY_INVOICE_SCOPE).First(&appPermission) + if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) { + logger.Logger.WithFields(logrus.Fields{ + "request_event_id": requestEventId, + }).WithError(result.Error).Error("Failed to fetch pay_invoice permission") + publishResponse(&models.Response{ + ResultType: nip47Request.Method, + Error: mapNip47Error(result.Error), + }, nostr.Tags{}) + return + } + // On ErrRecordNotFound appPermission stays zero-valued and maxAmountSat == 0, + // which returns the same empty "no budget" response as a permission with no + // budget set. maxAmountSat := appPermission.MaxAmountSat if maxAmountSat == 0 { publishResponse(&models.Response{ diff --git a/nip47/controllers/get_budget_controller_test.go b/nip47/controllers/get_budget_controller_test.go index b39b7194..8a6e6d72 100644 --- a/nip47/controllers/get_budget_controller_test.go +++ b/nip47/controllers/get_budget_controller_test.go @@ -207,6 +207,41 @@ func TestHandleGetBudgetEvent_NoBudget(t *testing.T) { assert.Nil(t, publishedResponse.Error) } +func TestHandleGetBudgetEvent_DatabaseError(t *testing.T) { + ctx := context.TODO() + svc, err := tests.CreateTestService(t) + require.NoError(t, err) + defer svc.Remove() + + nip47Request := &models.Request{} + err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request) + assert.NoError(t, err) + + app, _, err := tests.CreateApp(svc) + assert.NoError(t, err) + + dbRequestEvent := &db.RequestEvent{} + err = svc.DB.Create(&dbRequestEvent).Error + assert.NoError(t, err) + + // simulate a database failure that is not a record-not-found error + err = svc.DB.Exec("DROP TABLE app_permissions").Error + assert.NoError(t, err) + + var publishedResponse *models.Response + + publishResponse := func(response *models.Response, tags nostr.Tags) { + publishedResponse = response + } + + NewTestNip47Controller(svc). + HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse) + + assert.Nil(t, publishedResponse.Result) + require.NotNil(t, publishedResponse.Error) + assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code) +} + func TestHandleGetBudgetEvent_NoPayInvoicePermission(t *testing.T) { ctx := context.TODO() svc, err := tests.CreateTestService(t)