Skip to content

Commit

Permalink
feat(SPV-1478): migrate existing admin v2 endpoints to openapi3 (#899)
Browse files Browse the repository at this point in the history
Co-authored-by: Damian Orzepowski <[email protected]>
  • Loading branch information
pawellewandowski98 and dorzepowski authored Feb 14, 2025
1 parent c72a4cf commit 7d14887
Show file tree
Hide file tree
Showing 29 changed files with 1,172 additions and 276 deletions.
8 changes: 4 additions & 4 deletions actions/v2/admin/internal/mapping/paymail.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package mapping

import (
"github.com/bitcoin-sv/spv-wallet/api"
"github.com/bitcoin-sv/spv-wallet/engine/v2/paymails/paymailsmodels"
"github.com/bitcoin-sv/spv-wallet/models/response/adminresponse"
)

// PaymailToAdminResponse maps a paymail to a response
func PaymailToAdminResponse(p *paymailsmodels.Paymail) adminresponse.Paymail {
return adminresponse.Paymail{
ID: p.ID,
func PaymailToAdminResponse(p *paymailsmodels.Paymail) api.ModelsPaymail {
return api.ModelsPaymail{
Id: p.ID,
Alias: p.Alias,
Domain: p.Domain,
Paymail: p.Alias + "@" + p.Domain,
Expand Down
14 changes: 7 additions & 7 deletions actions/v2/admin/internal/mapping/user.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package mapping

import (
"github.com/bitcoin-sv/spv-wallet/api"
"github.com/bitcoin-sv/spv-wallet/engine/v2/users/usersmodels"
"github.com/bitcoin-sv/spv-wallet/lox"
"github.com/bitcoin-sv/spv-wallet/models/response/adminresponse"
"github.com/samber/lo"
)

// UserToResponse maps a user to a response
func UserToResponse(u *usersmodels.User) adminresponse.User {
return adminresponse.User{
ID: u.ID,
func UserToResponse(u *usersmodels.User) api.ModelsUser {
return api.ModelsUser{
Id: u.ID,
CreatedAt: u.CreatedAt,
UpdatedAt: u.UpdatedAt,
PublicKey: u.PublicKey,
Expand All @@ -19,9 +19,9 @@ func UserToResponse(u *usersmodels.User) adminresponse.User {
}

// UsersPaymailToResponse maps a user's paymail to a response
func UsersPaymailToResponse(p *usersmodels.Paymail) adminresponse.Paymail {
return adminresponse.Paymail{
ID: p.ID,
func UsersPaymailToResponse(p *usersmodels.Paymail) api.ModelsPaymail {
return api.ModelsPaymail{
Id: p.ID,
Alias: p.Alias,
Domain: p.Domain,
Paymail: p.Alias + "@" + p.Domain,
Expand Down
11 changes: 0 additions & 11 deletions actions/v2/admin/register.go

This file was deleted.

18 changes: 14 additions & 4 deletions actions/v2/admin/server.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package admin

// APIAdmin represents server with admin API endpoints
type APIAdmin struct{}
import (
"github.com/bitcoin-sv/spv-wallet/actions/v2/admin/users"
"github.com/bitcoin-sv/spv-wallet/engine"
"github.com/rs/zerolog"
)

// APIAdmin represents server with API endpoints
type APIAdmin struct {
users.APIAdminUsers
}

// NewAPIAdmin creates a new APIAdmin
func NewAPIAdmin() *APIAdmin {
return &APIAdmin{}
func NewAPIAdmin(spvWalletEngine engine.ClientInterface, logger *zerolog.Logger) APIAdmin {
return APIAdmin{
users.NewAPIAdminUsers(spvWalletEngine, logger),
}
}
4 changes: 2 additions & 2 deletions actions/v2/admin/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/gin-gonic/gin"
)

// GetApiV2AdminStatus return the status of the server only after admin authentication
func (s *APIAdmin) GetApiV2AdminStatus(c *gin.Context) {
// AdminStatus return the status of the server only after admin authentication
func (s *APIAdmin) AdminStatus(c *gin.Context) {
c.Status(http.StatusOK)
}
40 changes: 26 additions & 14 deletions actions/v2/admin/users/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ import (
primitives "github.com/bitcoin-sv/go-sdk/primitives/ec"
adminerrors "github.com/bitcoin-sv/spv-wallet/actions/v2/admin/errors"
"github.com/bitcoin-sv/spv-wallet/actions/v2/admin/internal/mapping"
"github.com/bitcoin-sv/spv-wallet/api"
configerrors "github.com/bitcoin-sv/spv-wallet/config/errors"
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/engine/v2/users/usersmodels"
"github.com/bitcoin-sv/spv-wallet/models/request/adminrequest"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)

func create(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)

var requestBody adminrequest.CreateUser
if err := c.Bind(&requestBody); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest.Wrap(err), logger)
// CreateUser creates a new user
func (s *APIAdminUsers) CreateUser(c *gin.Context) {
var request api.RequestsCreateUser
if err := c.Bind(&request); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest.Wrap(err), s.logger)
return
}

requestBody := &createUserRequest{&request}

if err := validatePubKey(requestBody.PublicKey); err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, err, s.logger)
return
}

newUser := &usersmodels.NewUser{
PublicKey: requestBody.PublicKey,
}
if requestBody.PaymailDefined() {
alias, domain, err := parsePaymail(requestBody.Paymail)
alias, domain, err := parsePaymail(requestBody.PaymailRequestBody())
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, err, s.logger)
return
}

Expand All @@ -43,13 +43,13 @@ func create(c *gin.Context, _ *reqctx.AdminContext) {
Domain: domain,

PublicName: requestBody.Paymail.PublicName,
Avatar: requestBody.Paymail.Avatar,
Avatar: requestBody.Paymail.AvatarURL,
}
}

createdUser, err := reqctx.Engine(c).UsersService().Create(c, newUser)
createdUser, err := s.engine.UsersService().Create(c, newUser)
if err != nil {
spverrors.MapResponse(c, err, logger).
spverrors.MapResponse(c, err, s.logger).
If(configerrors.ErrUnsupportedDomain).Then(adminerrors.ErrInvalidDomain).
Else(adminerrors.ErrCreatingUser)
return
Expand All @@ -65,3 +65,15 @@ func validatePubKey(pubKey string) error {
}
return nil
}

type createUserRequest struct {
*api.RequestsCreateUser
}

func (r *createUserRequest) PaymailDefined() bool {
return r.RequestsCreateUser.Paymail != nil
}

func (r *createUserRequest) PaymailRequestBody() *addPaymailRequest {
return &addPaymailRequest{r.RequestsCreateUser.Paymail}
}
10 changes: 4 additions & 6 deletions actions/v2/admin/users/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import (

"github.com/bitcoin-sv/spv-wallet/actions/v2/admin/internal/mapping"
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)

func get(c *gin.Context, _ *reqctx.AdminContext) {
userID := c.Param("id")

user, err := reqctx.Engine(c).UsersService().GetByID(c, userID)
// UserById returns a user by ID
func (s *APIAdminUsers) UserById(c *gin.Context, id string) {
user, err := s.engine.UsersService().GetByID(c, id)
if err != nil {
spverrors.ErrorResponse(c, err, reqctx.Logger(c))
spverrors.ErrorResponse(c, err, s.logger)
return
}

Expand Down
51 changes: 36 additions & 15 deletions actions/v2/admin/users/paymail_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,39 @@ import (
"github.com/bitcoin-sv/go-paymail"
adminerrors "github.com/bitcoin-sv/spv-wallet/actions/v2/admin/errors"
"github.com/bitcoin-sv/spv-wallet/actions/v2/admin/internal/mapping"
"github.com/bitcoin-sv/spv-wallet/api"
configerrors "github.com/bitcoin-sv/spv-wallet/config/errors"
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/engine/v2/paymails/paymailsmodels"
"github.com/bitcoin-sv/spv-wallet/models/request/adminrequest"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)

func addPaymail(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)

var requestBody adminrequest.AddPaymail
if err := c.Bind(&requestBody); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest.Wrap(err), logger)
// AddPaymailToUser add paymails to the user
func (s *APIAdminUsers) AddPaymailToUser(c *gin.Context, id string) {
var request api.RequestsAddPaymail
if err := c.Bind(&request); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest.Wrap(err), s.logger)
return
}

userID := c.Param("id")
requestBody := addPaymailRequest{&request}

alias, domain, err := parsePaymail(&requestBody)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, err, s.logger)
return
}

newPaymail := &paymailsmodels.NewPaymail{
Alias: alias,
Domain: domain,
PublicName: requestBody.PublicName,
Avatar: requestBody.Avatar,
UserID: userID,
Avatar: requestBody.AvatarURL,
UserID: id,
}
createdPaymail, err := reqctx.Engine(c).PaymailsService().Create(c, newPaymail)
createdPaymail, err := s.engine.PaymailsService().Create(c, newPaymail)
if err != nil {
spverrors.MapResponse(c, err, logger).
spverrors.MapResponse(c, err, s.logger).
If(configerrors.ErrUnsupportedDomain).Then(adminerrors.ErrInvalidDomain).
Else(adminerrors.ErrAddingPaymail)
return
Expand All @@ -52,7 +50,7 @@ func addPaymail(c *gin.Context, _ *reqctx.AdminContext) {
// parsePaymail parses the paymail address from the request body.
// Uses either Alias + Domain or the whole paymail Address field
// If both Alias + Domain and Address are set, and they are inconsistent, an error is returned.
func parsePaymail(request *adminrequest.AddPaymail) (string, string, error) {
func parsePaymail(request *addPaymailRequest) (string, string, error) {
if request.HasAddress() &&
(request.HasAlias() || request.HasDomain()) &&
!request.AddressEqualsTo(request.Alias+"@"+request.Domain) {
Expand All @@ -67,3 +65,26 @@ func parsePaymail(request *adminrequest.AddPaymail) (string, string, error) {
}
return alias, domain, nil
}

type addPaymailRequest struct {
*api.RequestsAddPaymail
}

func (a addPaymailRequest) HasAddress() bool {
return a.Address != ""
}

// HasAlias returns true if the paymail alias is set
func (a addPaymailRequest) HasAlias() bool {
return a.Alias != ""
}

// HasDomain returns true if the paymail domain is set
func (a addPaymailRequest) HasDomain() bool {
return a.Domain != ""
}

// AddressEqualsTo returns true if the paymail address is equal to the given string
func (a addPaymailRequest) AddressEqualsTo(s string) bool {
return a.Address == s
}
15 changes: 0 additions & 15 deletions actions/v2/admin/users/routes.go

This file was deleted.

20 changes: 20 additions & 0 deletions actions/v2/admin/users/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package users

import (
"github.com/bitcoin-sv/spv-wallet/engine"
"github.com/rs/zerolog"
)

// APIAdminUsers represents server with admin API endpoints
type APIAdminUsers struct {
engine engine.ClientInterface
logger *zerolog.Logger
}

// NewAPIAdminUsers creates a new APIAdminUsers
func NewAPIAdminUsers(engine engine.ClientInterface, logger *zerolog.Logger) APIAdminUsers {
return APIAdminUsers{
engine: engine,
logger: logger,
}
}
4 changes: 2 additions & 2 deletions actions/v2/base/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ type APIBase struct {
}

// NewAPIBase creates a new APIBase with config
func NewAPIBase(config *config.AppConfig) *APIBase {
return &APIBase{config}
func NewAPIBase(config *config.AppConfig) APIBase {
return APIBase{config}
}
9 changes: 5 additions & 4 deletions actions/v2/base/shared_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ package base
import (
"net/http"

"github.com/bitcoin-sv/spv-wallet/models/response"
"github.com/bitcoin-sv/spv-wallet/api"
"github.com/gin-gonic/gin"
)

// GetApiV2ConfigsShared is the handler for SharedConfig which can be obtained by both admin and user
func (s *APIBase) GetApiV2ConfigsShared(c *gin.Context) {
sharedConfig := response.SharedConfig{
// SharedConfig is the handler for SharedConfig which can be obtained by both admin and user
func (s *APIBase) SharedConfig(c *gin.Context) {
sharedConfig := api.ResponsesSharedConfig{
PaymailDomains: s.config.Paymail.Domains,
ExperimentalFeatures: map[string]bool{
"pikeContactsEnabled": s.config.ExperimentalFeatures.PikeContactsEnabled,
"pikePaymentEnabled": s.config.ExperimentalFeatures.PikePaymentEnabled,
"v2": s.config.ExperimentalFeatures.V2,
},
}

Expand Down
6 changes: 4 additions & 2 deletions actions/v2/base/shared_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ func TestGETConfigsShared(t *testing.T) {
"paymailDomains": ["example.com"],
"experimentalFeatures": {
"pikeContactsEnabled": true,
"pikePaymentEnabled": true
"pikePaymentEnabled": true,
"v2": true
}
}`)
})
Expand All @@ -52,7 +53,8 @@ func TestGETConfigsShared(t *testing.T) {
"paymailDomains": ["example.com"],
"experimentalFeatures": {
"pikeContactsEnabled": true,
"pikePaymentEnabled": true
"pikePaymentEnabled": true,
"v2": true
}
}`)

Expand Down
Loading

0 comments on commit 7d14887

Please sign in to comment.