Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(SPV-1471): add configs shared v2 endpoint #897

Merged
merged 8 commits into from
Feb 12, 2025
4 changes: 4 additions & 0 deletions actions/v2/admin/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package admin

// APIAdmin represents server with admin API endpoints
type APIAdmin struct{}
5 changes: 1 addition & 4 deletions actions/v2/admin/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import (
"github.com/gin-gonic/gin"
)

// Server represents server with API endpoints
type Server struct{}

// GetApiV2AdminStatus return the status of the server only after admin authentication
func (s *Server) GetApiV2AdminStatus(c *gin.Context) {
func (s *APIAdmin) GetApiV2AdminStatus(c *gin.Context) {
c.Status(http.StatusOK)
}
4 changes: 4 additions & 0 deletions actions/v2/base/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package base

// APIBase represents server with base API endpoints
type APIBase struct{}
26 changes: 26 additions & 0 deletions actions/v2/base/shared_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package base

import (
"net/http"
"sync"

"github.com/bitcoin-sv/spv-wallet/api"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"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) {
appconfig := reqctx.AppConfig(c)
dorzepowski marked this conversation as resolved.
Show resolved Hide resolved
makeConfig := sync.OnceValue(func() api.ApiComponentsResponsesSharedConfig {
return api.ApiComponentsResponsesSharedConfig{
PaymailDomains: &appconfig.Paymail.Domains,
ExperimentalFeatures: &map[string]bool{
"pikeContactsEnabled": appconfig.ExperimentalFeatures.PikeContactsEnabled,
"pikePaymentEnabled": appconfig.ExperimentalFeatures.PikePaymentEnabled,
},
}
})
dorzepowski marked this conversation as resolved.
Show resolved Hide resolved

c.JSON(http.StatusOK, makeConfig())
}
72 changes: 72 additions & 0 deletions actions/v2/base/shared_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package base_test

import (
"testing"

"github.com/bitcoin-sv/spv-wallet/actions/testabilities"
"github.com/bitcoin-sv/spv-wallet/config"
testengine "github.com/bitcoin-sv/spv-wallet/engine/testabilities"
)

func TestGETConfigsShared(t *testing.T) {
givenForAllTests := testabilities.Given(t)
cleanup := givenForAllTests.StartedSPVWalletWithConfiguration(func(cfg *config.AppConfig) {
cfg.Paymail.Domains = []string{"example.com"}
cfg.ExperimentalFeatures.PikePaymentEnabled = true
cfg.ExperimentalFeatures.PikeContactsEnabled = true
}, testengine.WithV2())
defer cleanup()

t.Run("return shared config for admin", func(t *testing.T) {
// given:
given, then := testabilities.NewOf(givenForAllTests, t)
client := given.HttpClient().ForAdmin()

// when:
res, _ := client.R().Get("/api/v2/configs/shared")

// then:
then.Response(res).
IsOK().
WithJSONf(`{
"paymailDomains": ["example.com"],
"experimentalFeatures": {
"pikeContactsEnabled": true,
"pikePaymentEnabled": true
}
}`)
})

t.Run("return shared config for user", func(t *testing.T) {
// given:
given, then := testabilities.NewOf(givenForAllTests, t)
client := given.HttpClient().ForUser()

// when:
res, _ := client.R().Get("/api/v2/configs/shared")

// then:
then.Response(res).
IsOK().
WithJSONf(`{
"paymailDomains": ["example.com"],
"experimentalFeatures": {
"pikeContactsEnabled": true,
"pikePaymentEnabled": true
}
}`)

})

t.Run("return unauthorized for anonymous requests", func(t *testing.T) {
// given
given, then := testabilities.NewOf(givenForAllTests, t)
client := given.HttpClient().ForAnonymous()

// when:
res, _ := client.R().Get("/api/v2/configs/shared")

// then:
then.Response(res).IsUnauthorized()
})
}
4 changes: 3 additions & 1 deletion actions/v2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package v2

import (
"github.com/bitcoin-sv/spv-wallet/actions/v2/admin"
"github.com/bitcoin-sv/spv-wallet/actions/v2/base"
"github.com/bitcoin-sv/spv-wallet/api"
)

// Server is the implementation of the server oapi-codegen's interface
type Server struct {
admin.Server
admin.APIAdmin
base.APIBase
}

// check if the Server implements the interface api.ServerInterface
Expand Down
14 changes: 14 additions & 0 deletions api/components/models.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,17 @@ info:

components:
schemas:
SharedConfig:
description: Shared config
type: object
properties:
paymailDomains:
type: array
items:
type: string
example: ["example.com"]
experimentalFeatures:
type: object
additionalProperties:
type: boolean
example: {"pikeEnabled": true}
8 changes: 7 additions & 1 deletion api/components/responses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ info:
version: ignored

components:
schemas:
responses:
SharedConfig:
description: Shared config
content:
application/json:
schema:
$ref: "./models.yaml#/components/schemas/SharedConfig"
dorzepowski marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 17 additions & 0 deletions api/endpoints/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,20 @@ info:
title: ignored
version: ignored
paths:

/api/v2/configs/shared:
get:
security:
- XPubAuth:
- "admin"
- "user"
tags:
- Base endpoints
pawellewandowski98 marked this conversation as resolved.
Show resolved Hide resolved
summary: Get shared config
description: >-
This endpoint returns shared config. It can be obtained by both admin and user.
responses:
200:
$ref: "../components/responses.yaml#/components/responses/SharedConfig"
401:
$ref: "../components/errors.yaml#/components/responses/NotAuthorized"
19 changes: 19 additions & 0 deletions api/gen.api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions api/gen.api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ paths:
summary: Get admin status
tags:
- Admin endpoints
/api/v2/configs/shared:
get:
description: This endpoint returns shared config. It can be obtained by both admin and user.
responses:
"200":
$ref: '#/components/responses/api_components_responses_SharedConfig'
"401":
$ref: '#/components/responses/api_components_errors_NotAuthorized'
security:
- XPubAuth:
- admin
- user
summary: Get shared config
tags:
- Base endpoints
components:
responses:
api_components_errors_NotAuthorized:
Expand All @@ -28,6 +43,12 @@ components:
schema:
$ref: '#/components/schemas/api_components_errors_ErrUnauthorized'
description: Security requirements failed
api_components_responses_SharedConfig:
content:
application/json:
schema:
$ref: '#/components/schemas/api_components_models_SharedConfig'
description: Shared config
schemas:
api_components_errors_ErrAdminAuthOnNonAdminEndpoint:
allOf:
Expand Down Expand Up @@ -84,6 +105,22 @@ components:
- code
- message
type: object
api_components_models_SharedConfig:
description: Shared config
properties:
experimentalFeatures:
additionalProperties:
example:
pikeEnabled: true
type: boolean
type: object
paymailDomains:
items:
example:
- example.com
type: string
type: array
type: object
securitySchemes:
XPubAuth:
description: Authentication using x-auth-xpub header
Expand Down
9 changes: 9 additions & 0 deletions api/gen.models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading