From f6a326697d1beebf0937e3f534b2c262341d8fbe Mon Sep 17 00:00:00 2001 From: im-adithya Date: Wed, 13 Dec 2023 13:34:43 +0530 Subject: [PATCH] chore: tests and fixes --- handle_info_request.go | 2 +- handle_pay_keysend_request.go | 8 ++- service_test.go | 114 +++++++++++++++++++++++++++++----- 3 files changed, 105 insertions(+), 19 deletions(-) diff --git a/handle_info_request.go b/handle_info_request.go index 799eed18..9864bff5 100644 --- a/handle_info_request.go +++ b/handle_info_request.go @@ -21,7 +21,7 @@ func (svc *Service) HandleGetInfoEvent(ctx context.Context, request *Nip47Reques return nil, err } - hasPermission, code, message := svc.hasPermission(&app, event, request.Method, nil) + hasPermission, code, message := svc.hasPermission(&app, event, request.Method, 0) if !hasPermission { svc.Logger.WithFields(logrus.Fields{ diff --git a/handle_pay_keysend_request.go b/handle_pay_keysend_request.go index 4cdb5b78..35815749 100644 --- a/handle_pay_keysend_request.go +++ b/handle_pay_keysend_request.go @@ -33,7 +33,11 @@ func (svc *Service) HandlePayKeysendEvent(ctx context.Context, request *Nip47Req return nil, err } - hasPermission, code, message := svc.hasPermission(&app, event, request.Method, payParams.Amount) + hasPermission, code, message := svc.hasPermission(&app, event, request.Method, 0) + if hasPermission { + // We use pay_invoice permissions for budget and max amount + hasPermission, code, message = svc.hasPermission(&app, event, NIP_47_PAY_INVOICE_METHOD, payParams.Amount) + } if !hasPermission { svc.Logger.WithFields(logrus.Fields{ @@ -89,7 +93,7 @@ func (svc *Service) HandlePayKeysendEvent(ctx context.Context, request *Nip47Req return svc.createResponse(event, Nip47Response{ ResultType: request.Method, Result: Nip47PayResponse{ - Preimage: preimage, + Preimage: preimage, }, }, ss) } diff --git a/service_test.go b/service_test.go index b005822c..f147e264 100644 --- a/service_test.go +++ b/service_test.go @@ -47,27 +47,40 @@ const nip47LookupInvoiceJson = ` } } ` +const nip47KeysendJson = ` +{ + "method": "pay_keysend", + "params": { + "amount": 100, + "pubkey": "123pubkey", + "tlv_records": [{ + "type": 5482373484, + "value": "fajsn341414fq" + }] + } +} +` const nip47PayJson = ` { "method": "pay_invoice", - "params": { - "invoice": "lntb1230n1pjypux0pp5xgxzcks5jtx06k784f9dndjh664wc08ucrganpqn52d0ftrh9n8sdqyw3jscqzpgxqyz5vqsp5rkx7cq252p3frx8ytjpzc55rkgyx2mfkzzraa272dqvr2j6leurs9qyyssqhutxa24r5hqxstchz5fxlslawprqjnarjujp5sm3xj7ex73s32sn54fthv2aqlhp76qmvrlvxppx9skd3r5ut5xutgrup8zuc6ay73gqmra29m" + "params": { + "invoice": "lntb1230n1pjypux0pp5xgxzcks5jtx06k784f9dndjh664wc08ucrganpqn52d0ftrh9n8sdqyw3jscqzpgxqyz5vqsp5rkx7cq252p3frx8ytjpzc55rkgyx2mfkzzraa272dqvr2j6leurs9qyyssqhutxa24r5hqxstchz5fxlslawprqjnarjujp5sm3xj7ex73s32sn54fthv2aqlhp76qmvrlvxppx9skd3r5ut5xutgrup8zuc6ay73gqmra29m" } } ` const nip47PayWrongMethodJson = ` { "method": "get_balance", - "params": { - "invoice": "lntb1230n1pjypux0pp5xgxzcks5jtx06k784f9dndjh664wc08ucrganpqn52d0ftrh9n8sdqyw3jscqzpgxqyz5vqsp5rkx7cq252p3frx8ytjpzc55rkgyx2mfkzzraa272dqvr2j6leurs9qyyssqhutxa24r5hqxstchz5fxlslawprqjnarjujp5sm3xj7ex73s32sn54fthv2aqlhp76qmvrlvxppx9skd3r5ut5xutgrup8zuc6ay73gqmra29m" + "params": { + "invoice": "lntb1230n1pjypux0pp5xgxzcks5jtx06k784f9dndjh664wc08ucrganpqn52d0ftrh9n8sdqyw3jscqzpgxqyz5vqsp5rkx7cq252p3frx8ytjpzc55rkgyx2mfkzzraa272dqvr2j6leurs9qyyssqhutxa24r5hqxstchz5fxlslawprqjnarjujp5sm3xj7ex73s32sn54fthv2aqlhp76qmvrlvxppx9skd3r5ut5xutgrup8zuc6ay73gqmra29m" } } ` const nip47PayJsonNoInvoice = ` { "method": "pay_invoice", - "params": { - "something": "else" + "params": { + "something": "else" } } ` @@ -277,6 +290,77 @@ func TestHandleEvent(t *testing.T) { assert.NoError(t, err) assert.Equal(t, NIP_47_ERROR_RESTRICTED, received.Error.Code) assert.NotNil(t, res) + + // pay_keysend: without permission + newPayload, err = nip04.Encrypt(nip47KeysendJson, ss) + assert.NoError(t, err) + res, err = svc.HandleEvent(ctx, &nostr.Event{ + ID: "test_pay_keysend_event_1", + Kind: NIP_47_REQUEST_KIND, + PubKey: senderPubkey, + Content: newPayload, + }) + assert.NoError(t, err) + assert.NotNil(t, res) + decrypted, err = nip04.Decrypt(res.Content, ss) + assert.NoError(t, err) + received = &Nip47Response{} + err = json.Unmarshal([]byte(decrypted), received) + assert.NoError(t, err) + assert.Equal(t, NIP_47_ERROR_RESTRICTED, received.Error.Code) + assert.NotNil(t, res) + // pay_keysend: with permission + // update the existing permission to pay_invoice so we can have the budget info and increase max amount + newMaxAmount = 1000 + err = svc.db.Model(&AppPermission{}).Where("app_id = ?", app.ID).Update("request_method", NIP_47_PAY_INVOICE_METHOD).Update("max_amount", newMaxAmount).Error + assert.NoError(t, err) + // create a second permission for getting the budget + appPermission = &AppPermission{ + AppId: app.ID, + App: app, + RequestMethod: NIP_47_PAY_KEYSEND_METHOD, + ExpiresAt: expiresAt, + } + err = svc.db.Create(appPermission).Error + res, err = svc.HandleEvent(ctx, &nostr.Event{ + ID: "test_pay_keysend_event_2", + Kind: NIP_47_REQUEST_KIND, + PubKey: senderPubkey, + Content: newPayload, + }) + assert.NoError(t, err) + assert.NotNil(t, res) + decrypted, err = nip04.Decrypt(res.Content, ss) + assert.NoError(t, err) + received = &Nip47Response{ + Result: &Nip47PayResponse{}, + } + err = json.Unmarshal([]byte(decrypted), received) + assert.NoError(t, err) + assert.Equal(t, "123preimage", received.Result.(*Nip47PayResponse).Preimage) + + // keysend: budget overflow + newMaxAmount = 100 + // we change the budget info in pay_invoice permission + err = svc.db.Model(&AppPermission{}).Where("request_method = ?", NIP_47_PAY_INVOICE_METHOD).Update("max_amount", newMaxAmount).Error + res, err = svc.HandleEvent(ctx, &nostr.Event{ + ID: "test_pay_keysend_event_3", + Kind: NIP_47_REQUEST_KIND, + PubKey: senderPubkey, + Content: newPayload, + }) + assert.NoError(t, err) + assert.NotNil(t, res) + decrypted, err = nip04.Decrypt(res.Content, ss) + assert.NoError(t, err) + received = &Nip47Response{ + Result: &Nip47PayResponse{}, + } + err = json.Unmarshal([]byte(decrypted), received) + assert.NoError(t, err) + assert.Equal(t, NIP_47_ERROR_QUOTA_EXCEEDED, received.Error.Code) + assert.NotNil(t, res) + // get_balance: without permission newPayload, err = nip04.Encrypt(nip47GetBalanceJson, ss) assert.NoError(t, err) @@ -296,10 +380,8 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, NIP_47_ERROR_RESTRICTED, received.Error.Code) assert.NotNil(t, res) // get_balance: with permission - // update the existing permission to pay_invoice so we can get the budget info - err = svc.db.Model(&AppPermission{}).Where("app_id = ?", app.ID).Update("request_method", NIP_47_PAY_INVOICE_METHOD).Error - assert.NoError(t, err) - // create a second permission for getting the budget + // the pay_invoice permmission already exists with the budget info + // create a second permission to fetch the balance and budget info appPermission = &AppPermission{ AppId: app.ID, App: app, @@ -326,7 +408,7 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, 100000, received.Result.(*Nip47BalanceResponse).MaxAmount) assert.Equal(t, "never", received.Result.(*Nip47BalanceResponse).BudgetRenewal) - // make invoice: without permission + // make_invoice: without permission newPayload, err = nip04.Encrypt(nip47MakeInvoiceJson, ss) assert.NoError(t, err) res, err = svc.HandleEvent(ctx, &nostr.Event{ @@ -345,7 +427,7 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, NIP_47_ERROR_RESTRICTED, received.Error.Code) assert.NotNil(t, res) - // make invoice: with permission + // make_invoice: with permission err = svc.db.Model(&AppPermission{}).Where("app_id = ?", app.ID).Update("request_method", NIP_47_MAKE_INVOICE_METHOD).Error res, err = svc.HandleEvent(ctx, &nostr.Event{ ID: "test_event_13", @@ -365,7 +447,7 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, mockInvoice, received.Result.(*Nip47MakeInvoiceResponse).Invoice) assert.Equal(t, mockPaymentHash, received.Result.(*Nip47MakeInvoiceResponse).PaymentHash) - // lookup invoice: without permission + // lookup_invoice: without permission newPayload, err = nip04.Encrypt(nip47LookupInvoiceJson, ss) assert.NoError(t, err) res, err = svc.HandleEvent(ctx, &nostr.Event{ @@ -384,7 +466,7 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, NIP_47_ERROR_RESTRICTED, received.Error.Code) assert.NotNil(t, res) - // lookup invoice: with permission + // lookup_invoice: with permission err = svc.db.Model(&AppPermission{}).Where("app_id = ?", app.ID).Update("request_method", NIP_47_LOOKUP_INVOICE_METHOD).Error assert.NoError(t, err) res, err = svc.HandleEvent(ctx, &nostr.Event{ @@ -405,7 +487,7 @@ func TestHandleEvent(t *testing.T) { assert.Equal(t, mockInvoice, received.Result.(*Nip47LookupInvoiceResponse).Invoice) assert.Equal(t, false, received.Result.(*Nip47LookupInvoiceResponse).Paid) - // get info: without permission + // get_info: without permission newPayload, err = nip04.Encrypt(nip47GetInfoJson, ss) assert.NoError(t, err) res, err = svc.HandleEvent(ctx, &nostr.Event{ @@ -427,7 +509,7 @@ func TestHandleEvent(t *testing.T) { // delete all permissions svc.db.Exec("delete from app_permissions") - // lookup invoice: with permission + // get_info: with permission appPermission = &AppPermission{ AppId: app.ID, App: app,