From 7d7abfe0b5b238c81fcd099545003d591952847d Mon Sep 17 00:00:00 2001 From: nabil salah Date: Mon, 24 Mar 2025 13:55:21 +0200 Subject: [PATCH 1/5] feat: add support for updating public key Signed-off-by: nabil salah --- node-registrar/client/account.go | 12 +++++++++++ node-registrar/pkg/db/accounts.go | 13 +++++++++++ node-registrar/pkg/server/handlers.go | 31 +++++++++++++++++++++------ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/node-registrar/client/account.go b/node-registrar/client/account.go index 808fc52..8ffd862 100644 --- a/node-registrar/client/account.go +++ b/node-registrar/client/account.go @@ -38,6 +38,7 @@ func (c *RegistrarClient) UpdateAccount(opts ...UpdateAccountOpts) (err error) { type accountCfg struct { relays []string rmbEncKey string + publicKey string } type ( @@ -58,6 +59,12 @@ func UpdateAccountWithRMBEncKey(rmbEncKey string) UpdateAccountOpts { } } +func UpdateAccountWithPublicKey(publicKey string) UpdateAccountOpts { + return func(n *accountCfg) { + n.publicKey = publicKey + } +} + // EnsureAccount ensures that an account is created with specific seed/mnemonic. func (c *RegistrarClient) EnsureAccount(relays []string, rmbEncKey string) (account Account, err error) { return c.ensureAccount(relays, rmbEncKey) @@ -276,6 +283,7 @@ func parseUpdateAccountOpts(opts []UpdateAccountOpts) map[string]any { cfg := accountCfg{ rmbEncKey: "", relays: []string{}, + publicKey: "", } for _, opt := range opts { @@ -292,5 +300,9 @@ func parseUpdateAccountOpts(opts []UpdateAccountOpts) map[string]any { data["rmb_enc_key"] = cfg.rmbEncKey } + if len(cfg.publicKey) != 0 { + data["public_key"] = cfg.publicKey + } + return data } diff --git a/node-registrar/pkg/db/accounts.go b/node-registrar/pkg/db/accounts.go index c78dba7..507cac0 100644 --- a/node-registrar/pkg/db/accounts.go +++ b/node-registrar/pkg/db/accounts.go @@ -31,6 +31,19 @@ func (db *Database) UpdateAccount(twinID uint64, relays pq.StringArray, rmbEncKe return nil } +func (db *Database) UpdateAccountPK(twinID uint64, publicKey string) error { + result := db.gormDB.Model(&Account{}).Where("twin_id = ?", twinID).Updates(map[string]interface{}{ + "public_key": publicKey, + }) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + return ErrRecordNotFound + } + return nil +} + // GetAccountByTwinID retrieves an account by its twin ID func (db *Database) GetAccount(twinID uint64) (Account, error) { var account Account diff --git a/node-registrar/pkg/server/handlers.go b/node-registrar/pkg/server/handlers.go index d4cc2e2..cb455ec 100644 --- a/node-registrar/pkg/server/handlers.go +++ b/node-registrar/pkg/server/handlers.go @@ -582,6 +582,7 @@ func verifySignature(publicKey, chalange, signature []byte) (bool, error) { type UpdateAccountRequest struct { Relays pq.StringArray `json:"relays"` RMBEncKey string `json:"rmb_enc_key"` + PubKey string `json:"public_key,omitempty"` } // updateAccountHandler updates an account's relays and RMB encryption key @@ -616,16 +617,34 @@ func (s *Server) updateAccountHandler(c *gin.Context) { return } - err = s.db.UpdateAccount(twinID, req.Relays, req.RMBEncKey) - if err != nil { - if errors.Is(err, db.ErrRecordNotFound) { - c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) + if req.PubKey != "" && isValidPublicKey(req.PubKey) { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid Public Key format"}) + return + } + + if req.PubKey != "" { + err = s.db.UpdateAccountPK(twinID, req.PubKey) + if err != nil { + if errors.Is(err, db.ErrRecordNotFound) { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) + return + } + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) return } - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) - return } + if len(req.Relays) != 0 && req.RMBEncKey != "" { + err = s.db.UpdateAccount(twinID, req.Relays, req.RMBEncKey) + if err != nil { + if errors.Is(err, db.ErrRecordNotFound) { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) + return + } + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) + return + } + } c.JSON(http.StatusOK, gin.H{"message": "account updated successfully"}) } From 7edbed0c48ad528728b3b73636f390a10fc5dded Mon Sep 17 00:00:00 2001 From: nabil salah Date: Mon, 24 Mar 2025 14:01:03 +0200 Subject: [PATCH 2/5] fix: linting Signed-off-by: nabil salah --- node-registrar/pkg/db/accounts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node-registrar/pkg/db/accounts.go b/node-registrar/pkg/db/accounts.go index 507cac0..6f25047 100644 --- a/node-registrar/pkg/db/accounts.go +++ b/node-registrar/pkg/db/accounts.go @@ -33,7 +33,7 @@ func (db *Database) UpdateAccount(twinID uint64, relays pq.StringArray, rmbEncKe func (db *Database) UpdateAccountPK(twinID uint64, publicKey string) error { result := db.gormDB.Model(&Account{}).Where("twin_id = ?", twinID).Updates(map[string]interface{}{ - "public_key": publicKey, + "public_key": publicKey, }) if result.Error != nil { return result.Error From b7077275f80d99fcb919315397046e1581d2f3a2 Mon Sep 17 00:00:00 2001 From: nabil salah Date: Mon, 24 Mar 2025 14:49:48 +0200 Subject: [PATCH 3/5] fix: using one update function Signed-off-by: nabil salah --- node-registrar/pkg/db/accounts.go | 18 ++++---------- node-registrar/pkg/server/handlers.go | 34 ++++++++------------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/node-registrar/pkg/db/accounts.go b/node-registrar/pkg/db/accounts.go index 6f25047..bfb5d09 100644 --- a/node-registrar/pkg/db/accounts.go +++ b/node-registrar/pkg/db/accounts.go @@ -17,24 +17,16 @@ func (db *Database) CreateAccount(account *Account) error { } // UpdateAccount updates an account's relays and RMB encryption key -func (db *Database) UpdateAccount(twinID uint64, relays pq.StringArray, rmbEncKey string) error { - result := db.gormDB.Model(&Account{}).Where("twin_id = ?", twinID).Updates(map[string]interface{}{ +func (db *Database) UpdateAccount(twinID uint64, relays pq.StringArray, rmbEncKey string, publicKey string) error { + update := map[string]interface{}{ "relays": relays, "rmb_enc_key": rmbEncKey, - }) - if result.Error != nil { - return result.Error } - if result.RowsAffected == 0 { - return ErrRecordNotFound + if publicKey != "" { + update["public_key"] = publicKey } - return nil -} -func (db *Database) UpdateAccountPK(twinID uint64, publicKey string) error { - result := db.gormDB.Model(&Account{}).Where("twin_id = ?", twinID).Updates(map[string]interface{}{ - "public_key": publicKey, - }) + result := db.gormDB.Model(&Account{}).Where("twin_id = ?", twinID).Updates(update) if result.Error != nil { return result.Error } diff --git a/node-registrar/pkg/server/handlers.go b/node-registrar/pkg/server/handlers.go index cb455ec..310d9cd 100644 --- a/node-registrar/pkg/server/handlers.go +++ b/node-registrar/pkg/server/handlers.go @@ -617,33 +617,19 @@ func (s *Server) updateAccountHandler(c *gin.Context) { return } - if req.PubKey != "" && isValidPublicKey(req.PubKey) { - c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid Public Key format"}) - return - } + // if req.PubKey != "" && isValidPublicKey(req.PubKey) { + // c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid Public Key format"}) + // return + // } - if req.PubKey != "" { - err = s.db.UpdateAccountPK(twinID, req.PubKey) - if err != nil { - if errors.Is(err, db.ErrRecordNotFound) { - c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) - return - } - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) - return - } - } - - if len(req.Relays) != 0 && req.RMBEncKey != "" { - err = s.db.UpdateAccount(twinID, req.Relays, req.RMBEncKey) - if err != nil { - if errors.Is(err, db.ErrRecordNotFound) { - c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) - return - } - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) + err = s.db.UpdateAccount(twinID, req.Relays, req.RMBEncKey, req.PubKey) + if err != nil { + if errors.Is(err, db.ErrRecordNotFound) { + c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "account not found"}) return } + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to update account"}) + return } c.JSON(http.StatusOK, gin.H{"message": "account updated successfully"}) } From 19e92110b3cc79cd74b745302fee21f4d1ae6e12 Mon Sep 17 00:00:00 2001 From: nabil salah Date: Mon, 24 Mar 2025 14:51:21 +0200 Subject: [PATCH 4/5] feat: check public key in update validity Signed-off-by: nabil salah --- node-registrar/pkg/server/handlers.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/node-registrar/pkg/server/handlers.go b/node-registrar/pkg/server/handlers.go index 310d9cd..f49daea 100644 --- a/node-registrar/pkg/server/handlers.go +++ b/node-registrar/pkg/server/handlers.go @@ -617,10 +617,10 @@ func (s *Server) updateAccountHandler(c *gin.Context) { return } - // if req.PubKey != "" && isValidPublicKey(req.PubKey) { - // c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid Public Key format"}) - // return - // } + if req.PubKey != "" && isValidPublicKey(req.PubKey) { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid Public Key format"}) + return + } err = s.db.UpdateAccount(twinID, req.Relays, req.RMBEncKey, req.PubKey) if err != nil { From 2910c238150231fa1a8979edbabf2f81b126658d Mon Sep 17 00:00:00 2001 From: nabil salah Date: Mon, 24 Mar 2025 15:06:01 +0200 Subject: [PATCH 5/5] fix: set non-zero feilds only for account update Signed-off-by: nabil salah --- node-registrar/pkg/db/accounts.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/node-registrar/pkg/db/accounts.go b/node-registrar/pkg/db/accounts.go index bfb5d09..1545307 100644 --- a/node-registrar/pkg/db/accounts.go +++ b/node-registrar/pkg/db/accounts.go @@ -18,9 +18,12 @@ func (db *Database) CreateAccount(account *Account) error { // UpdateAccount updates an account's relays and RMB encryption key func (db *Database) UpdateAccount(twinID uint64, relays pq.StringArray, rmbEncKey string, publicKey string) error { - update := map[string]interface{}{ - "relays": relays, - "rmb_enc_key": rmbEncKey, + update := map[string]interface{}{} + if len(relays) != 0 { + update["relays"] = relays + } + if rmbEncKey != "" { + update["rmb_enc_key"] = rmbEncKey } if publicKey != "" { update["public_key"] = publicKey