Skip to content

Commit

Permalink
chore: add extra tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz committed Dec 23, 2024
1 parent ec02564 commit 181eda1
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 6 deletions.
9 changes: 7 additions & 2 deletions apps/apps_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"slices"
"strings"
"time"

"github.com/getAlby/hub/constants"
Expand Down Expand Up @@ -44,9 +45,13 @@ func (svc *appsService) CreateApp(name string, pubkey string, maxAmountSat uint6
return nil, "", errors.New("isolated app cannot have sign_message scope")
}

// TODO: ensure there is at least one scope
if budgetRenewal == "" {
budgetRenewal = constants.BUDGET_RENEWAL_NEVER
}

// TODO: validate budget renewal
if !slices.Contains(constants.GetBudgetRenewals(), budgetRenewal) {
return nil, "", fmt.Errorf("invalid budget renewal. Must be one of %s", strings.Join(constants.GetBudgetRenewals(), ","))
}

var pairingPublicKey string
var pairingSecretKey string
Expand Down
10 changes: 10 additions & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ const (
BUDGET_RENEWAL_NEVER = "never"
)

func GetBudgetRenewals() []string {
return []string{
BUDGET_RENEWAL_DAILY,
BUDGET_RENEWAL_WEEKLY,
BUDGET_RENEWAL_MONTHLY,
BUDGET_RENEWAL_YEARLY,
BUDGET_RENEWAL_NEVER,
}
}

const (
PAY_INVOICE_SCOPE = "pay_invoice" // also covers pay_keysend and multi_* payment methods
GET_BALANCE_SCOPE = "get_balance"
Expand Down
12 changes: 12 additions & 0 deletions nip47/controllers/create_connection_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ func (controller *nip47Controller) HandleCreateConnectionEvent(ctx context.Conte
}
scopes, err := permissions.RequestMethodsToScopes(params.Methods)

// ensure there is at least one scope
if len(scopes) == 0 {
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Error: &models.Error{
Code: constants.ERROR_INTERNAL,
Message: "No methods provided",
},
}, nostr.Tags{})
return
}

app, _, err := controller.appsService.CreateApp(params.Name, params.Pubkey, params.Budget.Budget, params.Budget.RenewalPeriod, expiresAt, scopes, params.Isolated, params.Metadata)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
Expand Down
190 changes: 187 additions & 3 deletions nip47/controllers/create_connection_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,190 @@ func TestHandleCreateConnectionEvent(t *testing.T) {
assert.Equal(t, constants.GET_INFO_SCOPE, permissions[0].Scope)
}

// TODO: app already exists test
// TODO: validation - no pubkey, no scopes, wrong budget etc,
// TODO: ensure lnclient supports the methods
func TestHandleCreateConnectionEvent_PubkeyAlreadyExists(t *testing.T) {
ctx := context.TODO()
defer tests.RemoveTestService()
svc, err := tests.CreateTestService()
require.NoError(t, err)

pairingSecretKey := nostr.GeneratePrivateKey()
pairingPublicKey, err := nostr.GetPublicKey(pairingSecretKey)
require.NoError(t, err)

_, _, err = svc.AppsService.CreateApp("Existing App", pairingPublicKey, 0, constants.BUDGET_RENEWAL_NEVER, nil, []string{models.GET_INFO_METHOD}, false, nil)

nip47CreateConnectionJson := fmt.Sprintf(`
{
"method": "create_connection",
"params": {
"pubkey": "%s",
"name": "Test 123",
"methods": ["get_info"]
}
}
`, pairingPublicKey)

nip47Request := &models.Request{}
err = json.Unmarshal([]byte(nip47CreateConnectionJson), nip47Request)
assert.NoError(t, err)

dbRequestEvent := &db.RequestEvent{}
err = svc.DB.Create(&dbRequestEvent).Error
assert.NoError(t, err)

var publishedResponse *models.Response

publishResponse := func(response *models.Response, tags nostr.Tags) {
publishedResponse = response
}

permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
NewNip47Controller(svc.LNClient, svc.DB, svc.EventPublisher, permissionsSvc, transactionsSvc, svc.AppsService).
HandleCreateConnectionEvent(ctx, nip47Request, dbRequestEvent.ID, publishResponse)

assert.NotNil(t, publishedResponse.Error)
assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
assert.Equal(t, "duplicated key not allowed", publishedResponse.Error.Message)
assert.Equal(t, models.CREATE_CONNECTION_METHOD, publishedResponse.ResultType)
assert.Nil(t, publishedResponse.Result)
}

func TestHandleCreateConnectionEvent_NoMethods(t *testing.T) {
ctx := context.TODO()
defer tests.RemoveTestService()
svc, err := tests.CreateTestService()
require.NoError(t, err)

pairingSecretKey := nostr.GeneratePrivateKey()
pairingPublicKey, err := nostr.GetPublicKey(pairingSecretKey)
require.NoError(t, err)

nip47CreateConnectionJson := fmt.Sprintf(`
{
"method": "create_connection",
"params": {
"pubkey": "%s",
"name": "Test 123"
}
}
`, pairingPublicKey)

nip47Request := &models.Request{}
err = json.Unmarshal([]byte(nip47CreateConnectionJson), nip47Request)
assert.NoError(t, err)

dbRequestEvent := &db.RequestEvent{}
err = svc.DB.Create(&dbRequestEvent).Error
assert.NoError(t, err)

var publishedResponse *models.Response

publishResponse := func(response *models.Response, tags nostr.Tags) {
publishedResponse = response
}

permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
NewNip47Controller(svc.LNClient, svc.DB, svc.EventPublisher, permissionsSvc, transactionsSvc, svc.AppsService).
HandleCreateConnectionEvent(ctx, nip47Request, dbRequestEvent.ID, publishResponse)

assert.NotNil(t, publishedResponse.Error)
assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
assert.Equal(t, "No methods provided", publishedResponse.Error.Message)
assert.Equal(t, models.CREATE_CONNECTION_METHOD, publishedResponse.ResultType)
assert.Nil(t, publishedResponse.Result)
}

func TestHandleCreateConnectionEvent_UnsupportedMethod(t *testing.T) {
ctx := context.TODO()
defer tests.RemoveTestService()
svc, err := tests.CreateTestService()
require.NoError(t, err)

pairingSecretKey := nostr.GeneratePrivateKey()
pairingPublicKey, err := nostr.GetPublicKey(pairingSecretKey)
require.NoError(t, err)

nip47CreateConnectionJson := fmt.Sprintf(`
{
"method": "create_connection",
"params": {
"pubkey": "%s",
"name": "Test 123",
"methods": ["non_existent"]
}
}
`, pairingPublicKey)

nip47Request := &models.Request{}
err = json.Unmarshal([]byte(nip47CreateConnectionJson), nip47Request)
assert.NoError(t, err)

dbRequestEvent := &db.RequestEvent{}
err = svc.DB.Create(&dbRequestEvent).Error
assert.NoError(t, err)

var publishedResponse *models.Response

publishResponse := func(response *models.Response, tags nostr.Tags) {
publishedResponse = response
}

permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
NewNip47Controller(svc.LNClient, svc.DB, svc.EventPublisher, permissionsSvc, transactionsSvc, svc.AppsService).
HandleCreateConnectionEvent(ctx, nip47Request, dbRequestEvent.ID, publishResponse)

assert.NotNil(t, publishedResponse.Error)
assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
assert.Equal(t, "One or more methods are not supported by the current LNClient", publishedResponse.Error.Message)
assert.Equal(t, models.CREATE_CONNECTION_METHOD, publishedResponse.ResultType)
assert.Nil(t, publishedResponse.Result)
}
func TestHandleCreateConnectionEvent_DoNotAllowCreateConnectionMethod(t *testing.T) {
ctx := context.TODO()
defer tests.RemoveTestService()
svc, err := tests.CreateTestService()
require.NoError(t, err)

pairingSecretKey := nostr.GeneratePrivateKey()
pairingPublicKey, err := nostr.GetPublicKey(pairingSecretKey)
require.NoError(t, err)

nip47CreateConnectionJson := fmt.Sprintf(`
{
"method": "create_connection",
"params": {
"pubkey": "%s",
"name": "Test 123",
"methods": ["create_connection"]
}
}
`, pairingPublicKey)

nip47Request := &models.Request{}
err = json.Unmarshal([]byte(nip47CreateConnectionJson), nip47Request)
assert.NoError(t, err)

dbRequestEvent := &db.RequestEvent{}
err = svc.DB.Create(&dbRequestEvent).Error
assert.NoError(t, err)

var publishedResponse *models.Response

publishResponse := func(response *models.Response, tags nostr.Tags) {
publishedResponse = response
}

permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
NewNip47Controller(svc.LNClient, svc.DB, svc.EventPublisher, permissionsSvc, transactionsSvc, svc.AppsService).
HandleCreateConnectionEvent(ctx, nip47Request, dbRequestEvent.ID, publishResponse)

assert.NotNil(t, publishedResponse.Error)
assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
assert.Equal(t, "One or more methods are not supported by the current LNClient", publishedResponse.Error.Message)
assert.Equal(t, models.CREATE_CONNECTION_METHOD, publishedResponse.ResultType)
assert.Nil(t, publishedResponse.Result)
}
2 changes: 1 addition & 1 deletion nip47/event_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func TestHandleResponse_WithPermission(t *testing.T) {
assert.Nil(t, unmarshalledResponse.Error)
assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
expectedMethods := slices.Concat([]string{constants.GET_BALANCE_SCOPE}, permissions.GetAlwaysGrantedMethods())
assert.Equal(t, expectedMethods, unmarshalledResponse.Result.Methods)
assert.ElementsMatch(t, expectedMethods, unmarshalledResponse.Result.Methods)
}

func TestHandleResponse_DuplicateRequest(t *testing.T) {
Expand Down

0 comments on commit 181eda1

Please sign in to comment.