get_info_controller_test.go raw

   1  package controllers
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"testing"
   7  
   8  	"github.com/getAlby/go-nostr"
   9  	"github.com/stretchr/testify/assert"
  10  	"github.com/stretchr/testify/require"
  11  
  12  	"github.com/getAlby/hub/config"
  13  	"github.com/getAlby/hub/constants"
  14  	"github.com/getAlby/hub/db"
  15  	"github.com/getAlby/hub/nip47/models"
  16  	"github.com/getAlby/hub/tests"
  17  )
  18  
  19  const nip47GetInfoJson = `
  20  {
  21  	"method": "get_info"
  22  }
  23  `
  24  
  25  func TestHandleGetInfoEvent_NoPermission(t *testing.T) {
  26  	ctx := context.TODO()
  27  	svc, err := tests.CreateTestService(t)
  28  	require.NoError(t, err)
  29  	defer svc.Remove()
  30  
  31  	metadata := map[string]interface{}{
  32  		"a": 123,
  33  	}
  34  
  35  	app, _, err := svc.AppsService.CreateApp("test", "", 0, "monthly", nil, []string{constants.GET_INFO_SCOPE}, false, metadata)
  36  	assert.NoError(t, err)
  37  
  38  	lightningAddress := "hello@getalby.com"
  39  	svc.Cfg.SetUpdate("AlbyLightningAddress", lightningAddress, "")
  40  
  41  	nip47Request := &models.Request{}
  42  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
  43  	assert.NoError(t, err)
  44  
  45  	dbRequestEvent := &db.RequestEvent{}
  46  	err = svc.DB.Create(&dbRequestEvent).Error
  47  	assert.NoError(t, err)
  48  
  49  	// delete the existing app permissions (the app was created with get_info scope)
  50  	svc.DB.Exec("delete from app_permissions")
  51  
  52  	appPermission := &db.AppPermission{
  53  		AppId:     app.ID,
  54  		Scope:     constants.GET_BALANCE_SCOPE,
  55  		ExpiresAt: nil,
  56  	}
  57  	err = svc.DB.Create(appPermission).Error
  58  	assert.NoError(t, err)
  59  
  60  	var publishedResponse *models.Response
  61  
  62  	publishResponse := func(response *models.Response, tags nostr.Tags) {
  63  		publishedResponse = response
  64  	}
  65  
  66  	NewTestNip47Controller(svc).
  67  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
  68  
  69  	assert.Nil(t, publishedResponse.Error)
  70  	infoResponse := publishedResponse.Result.(*getInfoResponse)
  71  	assert.Nil(t, infoResponse.Alias)
  72  	assert.Nil(t, infoResponse.Color)
  73  	assert.Nil(t, infoResponse.Pubkey)
  74  	assert.Nil(t, infoResponse.Network)
  75  	assert.Nil(t, infoResponse.BlockHeight)
  76  	assert.Nil(t, infoResponse.BlockHash)
  77  	require.NotNil(t, infoResponse.LightningAddress)
  78  	assert.Equal(t, lightningAddress, *infoResponse.LightningAddress)
  79  	// get_info method is always granted, but does not return pubkey
  80  	assert.Contains(t, infoResponse.Methods, models.GET_INFO_METHOD)
  81  	assert.Equal(t, []string{}, infoResponse.Notifications)
  82  	require.NotNil(t, infoResponse.Metadata)
  83  	assert.Equal(t, float64(123), infoResponse.Metadata.(map[string]interface{})["a"])
  84  	assert.Equal(t, app.ID, infoResponse.Metadata.(map[string]interface{})["id"])
  85  	assert.Equal(t, app.Name, infoResponse.Metadata.(map[string]interface{})["name"])
  86  }
  87  
  88  func TestHandleGetInfoEvent_SubwalletNoPermission(t *testing.T) {
  89  	ctx := context.TODO()
  90  	svc, err := tests.CreateTestService(t)
  91  	require.NoError(t, err)
  92  	defer svc.Remove()
  93  
  94  	lightningAddress := "hello@getalby.com"
  95  
  96  	metadata := map[string]interface{}{
  97  		constants.METADATA_APPSTORE_APP_ID_KEY: constants.SUBWALLET_APPSTORE_APP_ID,
  98  		"lud16":                                lightningAddress,
  99  	}
 100  
 101  	svc.Cfg.SetUpdate("LNBackendType", config.LDKBackendType, "")
 102  
 103  	app, _, err := svc.AppsService.CreateApp("test", "", 0, "monthly", nil, []string{constants.GET_INFO_SCOPE}, true, metadata)
 104  	assert.NoError(t, err)
 105  
 106  	nip47Request := &models.Request{}
 107  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
 108  	assert.NoError(t, err)
 109  
 110  	dbRequestEvent := &db.RequestEvent{}
 111  	err = svc.DB.Create(&dbRequestEvent).Error
 112  	assert.NoError(t, err)
 113  
 114  	// delete the existing app permissions (the app was created with get_info scope)
 115  	svc.DB.Exec("delete from app_permissions")
 116  
 117  	appPermission := &db.AppPermission{
 118  		AppId:     app.ID,
 119  		Scope:     constants.GET_BALANCE_SCOPE,
 120  		ExpiresAt: nil,
 121  	}
 122  	err = svc.DB.Create(appPermission).Error
 123  	assert.NoError(t, err)
 124  
 125  	var publishedResponse *models.Response
 126  
 127  	publishResponse := func(response *models.Response, tags nostr.Tags) {
 128  		publishedResponse = response
 129  	}
 130  
 131  	NewTestNip47Controller(svc).
 132  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
 133  
 134  	assert.Nil(t, publishedResponse.Error)
 135  	infoResponse := publishedResponse.Result.(*getInfoResponse)
 136  	assert.Nil(t, infoResponse.Alias)
 137  	assert.Nil(t, infoResponse.Color)
 138  	assert.Nil(t, infoResponse.Pubkey)
 139  	assert.Nil(t, infoResponse.Network)
 140  	assert.Nil(t, infoResponse.BlockHeight)
 141  	assert.Nil(t, infoResponse.BlockHash)
 142  	require.NotNil(t, infoResponse.LightningAddress)
 143  	assert.Equal(t, lightningAddress, *infoResponse.LightningAddress)
 144  	// get_info method is always granted, but does not return pubkey
 145  	assert.Contains(t, infoResponse.Methods, models.GET_INFO_METHOD)
 146  	assert.Equal(t, []string{}, infoResponse.Notifications)
 147  	require.NotNil(t, infoResponse.Metadata)
 148  	assert.Equal(t, lightningAddress, infoResponse.Metadata.(map[string]interface{})["lud16"])
 149  	assert.Equal(t, app.ID, infoResponse.Metadata.(map[string]interface{})["id"])
 150  	assert.Equal(t, app.Name, infoResponse.Metadata.(map[string]interface{})["name"])
 151  }
 152  
 153  func TestHandleGetInfoEvent_WithPermission(t *testing.T) {
 154  	ctx := context.TODO()
 155  	svc, err := tests.CreateTestService(t)
 156  	require.NoError(t, err)
 157  	defer svc.Remove()
 158  
 159  	app, _, err := tests.CreateApp(svc)
 160  	assert.NoError(t, err)
 161  
 162  	nip47Request := &models.Request{}
 163  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
 164  	assert.NoError(t, err)
 165  
 166  	dbRequestEvent := &db.RequestEvent{}
 167  	err = svc.DB.Create(&dbRequestEvent).Error
 168  	assert.NoError(t, err)
 169  
 170  	appPermission := &db.AppPermission{
 171  		AppId:     app.ID,
 172  		Scope:     constants.GET_INFO_SCOPE,
 173  		ExpiresAt: nil,
 174  	}
 175  	err = svc.DB.Create(appPermission).Error
 176  	assert.NoError(t, err)
 177  
 178  	var publishedResponse *models.Response
 179  
 180  	publishResponse := func(response *models.Response, tags nostr.Tags) {
 181  		publishedResponse = response
 182  	}
 183  
 184  	NewTestNip47Controller(svc).
 185  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
 186  
 187  	assert.Nil(t, publishedResponse.Error)
 188  	infoResponse := publishedResponse.Result.(*getInfoResponse)
 189  	assert.Equal(t, tests.MockNodeInfo.Alias, *infoResponse.Alias)
 190  	assert.Equal(t, tests.MockNodeInfo.Color, *infoResponse.Color)
 191  	assert.Equal(t, tests.MockNodeInfo.Pubkey, *infoResponse.Pubkey)
 192  	assert.Equal(t, tests.MockNodeInfo.Network, *infoResponse.Network)
 193  	assert.Equal(t, tests.MockNodeInfo.BlockHeight, *infoResponse.BlockHeight)
 194  	assert.Equal(t, tests.MockNodeInfo.BlockHash, *infoResponse.BlockHash)
 195  	assert.Contains(t, infoResponse.Methods, "get_info")
 196  	assert.Equal(t, []string{}, infoResponse.Notifications)
 197  }
 198  
 199  func TestHandleGetInfoEvent_WithMetadata(t *testing.T) {
 200  	ctx := context.TODO()
 201  	svc, err := tests.CreateTestService(t)
 202  	require.NoError(t, err)
 203  	defer svc.Remove()
 204  
 205  	lightningAddress := "hello@getalby.com"
 206  	svc.Cfg.SetUpdate("AlbyLightningAddress", lightningAddress, "")
 207  
 208  	metadata := map[string]interface{}{
 209  		"a": 123,
 210  	}
 211  
 212  	app, _, err := svc.AppsService.CreateApp("test", "", 0, "monthly", nil, []string{constants.GET_INFO_SCOPE}, false, metadata)
 213  	assert.NoError(t, err)
 214  
 215  	nip47Request := &models.Request{}
 216  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
 217  	assert.NoError(t, err)
 218  
 219  	dbRequestEvent := &db.RequestEvent{}
 220  	err = svc.DB.Create(&dbRequestEvent).Error
 221  	assert.NoError(t, err)
 222  
 223  	appPermission := &db.AppPermission{
 224  		AppId:     app.ID,
 225  		Scope:     constants.GET_INFO_SCOPE,
 226  		ExpiresAt: nil,
 227  	}
 228  	err = svc.DB.Create(appPermission).Error
 229  	assert.NoError(t, err)
 230  
 231  	var publishedResponse *models.Response
 232  
 233  	publishResponse := func(response *models.Response, tags nostr.Tags) {
 234  		publishedResponse = response
 235  	}
 236  
 237  	NewTestNip47Controller(svc).
 238  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
 239  
 240  	assert.Nil(t, publishedResponse.Error)
 241  	infoResponse := publishedResponse.Result.(*getInfoResponse)
 242  	assert.Equal(t, tests.MockNodeInfo.Alias, *infoResponse.Alias)
 243  	assert.Equal(t, tests.MockNodeInfo.Color, *infoResponse.Color)
 244  	assert.Equal(t, tests.MockNodeInfo.Pubkey, *infoResponse.Pubkey)
 245  	assert.Equal(t, tests.MockNodeInfo.Network, *infoResponse.Network)
 246  	assert.Equal(t, tests.MockNodeInfo.BlockHeight, *infoResponse.BlockHeight)
 247  	assert.Equal(t, tests.MockNodeInfo.BlockHash, *infoResponse.BlockHash)
 248  	assert.Equal(t, lightningAddress, *infoResponse.LightningAddress)
 249  	assert.Contains(t, infoResponse.Methods, "get_info")
 250  	assert.Equal(t, []string{}, infoResponse.Notifications)
 251  	assert.Equal(t, float64(123), infoResponse.Metadata.(map[string]interface{})["a"])
 252  }
 253  
 254  func TestHandleGetInfoEvent_SubwalletWithMetadata(t *testing.T) {
 255  	ctx := context.TODO()
 256  	svc, err := tests.CreateTestService(t)
 257  	require.NoError(t, err)
 258  	defer svc.Remove()
 259  
 260  	lightningAddress := "hello@getalby.com"
 261  
 262  	metadata := map[string]interface{}{
 263  		constants.METADATA_APPSTORE_APP_ID_KEY: constants.SUBWALLET_APPSTORE_APP_ID,
 264  		"lud16":                                lightningAddress,
 265  		"a":                                    123,
 266  	}
 267  
 268  	svc.Cfg.SetUpdate("LNBackendType", config.LDKBackendType, "")
 269  	app, _, err := svc.AppsService.CreateApp("test", "", 0, "monthly", nil, []string{constants.GET_INFO_SCOPE}, true, metadata)
 270  	assert.NoError(t, err)
 271  
 272  	nip47Request := &models.Request{}
 273  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
 274  	assert.NoError(t, err)
 275  
 276  	dbRequestEvent := &db.RequestEvent{}
 277  	err = svc.DB.Create(&dbRequestEvent).Error
 278  	assert.NoError(t, err)
 279  
 280  	appPermission := &db.AppPermission{
 281  		AppId:     app.ID,
 282  		Scope:     constants.GET_INFO_SCOPE,
 283  		ExpiresAt: nil,
 284  	}
 285  	err = svc.DB.Create(appPermission).Error
 286  	assert.NoError(t, err)
 287  
 288  	var publishedResponse *models.Response
 289  
 290  	publishResponse := func(response *models.Response, tags nostr.Tags) {
 291  		publishedResponse = response
 292  	}
 293  
 294  	NewTestNip47Controller(svc).
 295  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
 296  
 297  	assert.Nil(t, publishedResponse.Error)
 298  	infoResponse := publishedResponse.Result.(*getInfoResponse)
 299  	assert.Equal(t, tests.MockNodeInfo.Alias, *infoResponse.Alias)
 300  	assert.Equal(t, tests.MockNodeInfo.Color, *infoResponse.Color)
 301  	assert.Equal(t, tests.MockNodeInfo.Pubkey, *infoResponse.Pubkey)
 302  	assert.Equal(t, tests.MockNodeInfo.Network, *infoResponse.Network)
 303  	assert.Equal(t, tests.MockNodeInfo.BlockHeight, *infoResponse.BlockHeight)
 304  	assert.Equal(t, tests.MockNodeInfo.BlockHash, *infoResponse.BlockHash)
 305  	assert.Equal(t, lightningAddress, *infoResponse.LightningAddress)
 306  	assert.Contains(t, infoResponse.Methods, "get_info")
 307  	assert.Equal(t, []string{}, infoResponse.Notifications)
 308  	assert.Equal(t, float64(123), infoResponse.Metadata.(map[string]interface{})["a"])
 309  }
 310  
 311  func TestHandleGetInfoEvent_WithNotifications(t *testing.T) {
 312  	ctx := context.TODO()
 313  	svc, err := tests.CreateTestService(t)
 314  	require.NoError(t, err)
 315  	defer svc.Remove()
 316  
 317  	app, _, err := tests.CreateApp(svc)
 318  	assert.NoError(t, err)
 319  
 320  	nip47Request := &models.Request{}
 321  	err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
 322  	assert.NoError(t, err)
 323  
 324  	dbRequestEvent := &db.RequestEvent{}
 325  	err = svc.DB.Create(&dbRequestEvent).Error
 326  	assert.NoError(t, err)
 327  
 328  	appPermission := &db.AppPermission{
 329  		AppId:     app.ID,
 330  		Scope:     constants.GET_INFO_SCOPE,
 331  		ExpiresAt: nil,
 332  	}
 333  	err = svc.DB.Create(appPermission).Error
 334  	assert.NoError(t, err)
 335  
 336  	appPermission = &db.AppPermission{
 337  		AppId:     app.ID,
 338  		Scope:     constants.NOTIFICATIONS_SCOPE,
 339  		ExpiresAt: nil,
 340  	}
 341  	err = svc.DB.Create(appPermission).Error
 342  	assert.NoError(t, err)
 343  
 344  	var publishedResponse *models.Response
 345  
 346  	publishResponse := func(response *models.Response, tags nostr.Tags) {
 347  		publishedResponse = response
 348  	}
 349  
 350  	NewTestNip47Controller(svc).
 351  		HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
 352  
 353  	assert.Nil(t, publishedResponse.Error)
 354  	infoResponse := publishedResponse.Result.(*getInfoResponse)
 355  	assert.Equal(t, tests.MockNodeInfo.Alias, *infoResponse.Alias)
 356  	assert.Equal(t, tests.MockNodeInfo.Color, *infoResponse.Color)
 357  	assert.Equal(t, tests.MockNodeInfo.Pubkey, *infoResponse.Pubkey)
 358  	assert.Equal(t, tests.MockNodeInfo.Network, *infoResponse.Network)
 359  	assert.Equal(t, tests.MockNodeInfo.BlockHeight, *infoResponse.BlockHeight)
 360  	assert.Equal(t, tests.MockNodeInfo.BlockHash, *infoResponse.BlockHash)
 361  	assert.Contains(t, infoResponse.Methods, "get_info")
 362  	assert.Equal(t, []string{"payment_received", "payment_sent"}, infoResponse.Notifications)
 363  }
 364