alby-hub/nip47/controllers/get_info_controller.go
Roland 3e1d16d423
Feat: NWA auth for self-hosted hubs (#1016)
* feat: nwc create_connection command (WIP)

* feat: allow creating superuser apps from the ui

* fix: pass methods rather than scopes in create_connection method

* chore: add extra tests

* fix: use browser router in http mode

* fix: update links to not use hash router

* fix: add redirect from hash router url

* fix: return nostrWalletConnectUrl in nwc connection success event and message

* feat: publish nwa event

* chore: use nwc info event instead of nwa event

* feat: create custom alby go detail page

* chore: allow creating/editing apps with the same name

* fix: convert budget from msats to sats (#1111)

* chore: address NWA feedback

* chore: address feedback

- adjust button copy
- make create_connection methods consistent with http deeplink flow
- remove unused constant
- add empty string check before adding lud16 tag
- fix test

* feat: add support for notification_types in create_connection method

* fix: shorter button copy

* fix: do not include lud16 tag in published info event

* Feat: add lud16 to get_info response (#1128)

feat: add lud16 to get_info response

* chore: minor alby go screen improvements

* fix: incorrect unlock password error message to create app with superuser access

* chore: minor ui improvements on alby go detail page

* chore: avoid duplicate app names by adding a suffix

* chore: move scopes check to apps service, add new tests, DRY controller test setup

* fix: scopes component full access scopes and isolated scope group check

* fix: use supported capabilities for Alby Go

* fix: return correct app name

* chore: address minor comments

---------

Co-authored-by: im-adithya <imadithyavardhan@gmail.com>
2025-02-27 19:12:55 +07:00

107 lines
3.3 KiB
Go

package controllers
import (
"context"
"encoding/json"
"github.com/getAlby/hub/constants"
"github.com/getAlby/hub/db"
"github.com/getAlby/hub/logger"
"github.com/getAlby/hub/nip47/models"
"github.com/nbd-wtf/go-nostr"
"github.com/sirupsen/logrus"
)
type getInfoResponse struct {
Alias string `json:"alias"`
Color string `json:"color"`
Pubkey string `json:"pubkey"`
Network string `json:"network"`
BlockHeight uint32 `json:"block_height"`
BlockHash string `json:"block_hash"`
Methods []string `json:"methods"`
Notifications []string `json:"notifications"`
Metadata interface{} `json:"metadata,omitempty"`
LightningAddress string `json:"lud16"`
}
func (controller *nip47Controller) HandleGetInfoEvent(ctx context.Context, nip47Request *models.Request, requestEventId uint, app *db.App, publishResponse publishFunc) {
supportedNotifications := []string{}
if controller.permissionsService.PermitsNotifications(app) {
supportedNotifications = controller.lnClient.GetSupportedNIP47NotificationTypes()
}
responsePayload := &getInfoResponse{
Methods: controller.permissionsService.GetPermittedMethods(app, controller.lnClient),
Notifications: supportedNotifications,
}
// basic permissions check
// this is inconsistent with other methods. Ideally we move fetching node info to a separate method,
// so that get_info does not require its own scope. This would require a change in the NIP-47 spec.
hasPermission, _, _ := controller.permissionsService.HasPermission(app, constants.GET_INFO_SCOPE)
if hasPermission {
logger.Logger.WithFields(logrus.Fields{
"request_event_id": requestEventId,
}).Debug("Getting info")
info, err := controller.lnClient.GetInfo(ctx)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"request_event_id": requestEventId,
}).Infof("Failed to fetch node info: %v", err)
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Error: &models.Error{
Code: constants.ERROR_INTERNAL,
Message: err.Error(),
},
}, nostr.Tags{})
return
}
network := info.Network
// Some implementations return "bitcoin" while NIP47 expects "mainnet"
if network == "bitcoin" {
network = "mainnet"
}
responsePayload.Alias = info.Alias
responsePayload.Color = info.Color
responsePayload.Pubkey = info.Pubkey
responsePayload.Network = network
responsePayload.BlockHeight = info.BlockHeight
responsePayload.BlockHash = info.BlockHash
if app != nil {
metadata := map[string]interface{}{}
if app.Metadata != nil {
jsonErr := json.Unmarshal(app.Metadata, &metadata)
if jsonErr != nil {
logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
"id": app.ID,
"metadata": app.Metadata,
}).Error("Failed to deserialize app metadata")
}
}
if metadata["id"] == nil {
metadata["id"] = app.ID
}
if metadata["name"] == nil {
metadata["name"] = app.Name
}
if !app.Isolated {
lightningAddress, _ := controller.albyOAuthService.GetLightningAddress()
responsePayload.LightningAddress = lightningAddress
}
responsePayload.Metadata = metadata
}
}
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Result: responsePayload,
}, nostr.Tags{})
}