Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

SPV-838(feat) AdminAPI #744

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 17 additions & 45 deletions actions/admin/access_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"net/http"

"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/internal/query"
"github.com/bitcoin-sv/spv-wallet/mappings"
"github.com/bitcoin-sv/spv-wallet/models"
"github.com/bitcoin-sv/spv-wallet/models/filter"
"github.com/bitcoin-sv/spv-wallet/models/response"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)
Expand All @@ -18,67 +19,38 @@ import (
// @Tags Admin
// @Produce json
// @Param SearchAccessKeys body filter.AdminSearchAccessKeys false "Supports targeted resource searches with filters and metadata, plus options for pagination and sorting to streamline data exploration and analysis"
// @Success 200 {object} []models.AccessKey "List of access keys"
// @Success 200 {object} []response.AccessKey "List of access keys"
// @Failure 400 "Bad request - Error while parsing SearchAccessKeys from request body"
// @Failure 500 "Internal server error - Error while searching for access keys"
// @Router /v1/admin/access-keys/search [post]
// @Router /api/v1/admin/users/keys [get]
// @Security x-auth-xpub
func accessKeysSearch(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
var reqParams filter.AdminSearchAccessKeys
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
searchParams, err := query.ParseSearchParams[filter.AdminAccessKeyFilter](c)
if err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotParseQueryParams.WithTrace(err), logger)
return
}

conditions := searchParams.Conditions.ToDbConditions()
metadata := mappings.MapToMetadata(searchParams.Metadata)
pageOptions := mappings.MapToDbQueryParams(&searchParams.Page)

accessKeys, err := reqctx.Engine(c).GetAccessKeys(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
reqParams.Conditions.ToDbConditions(),
mappings.MapToQueryParams(reqParams.QueryParams),
metadata,
conditions,
pageOptions,
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, spverrors.ErrCouldNotFindAccessKey.WithTrace(err), logger)
return
}

accessKeyContracts := make([]*models.AccessKey, 0)
accessKeyContracts := make([]*response.AccessKey, 0, len(accessKeys))
for _, accessKey := range accessKeys {
accessKeyContracts = append(accessKeyContracts, mappings.MapToOldAccessKeyContract(accessKey))
accessKeyContracts = append(accessKeyContracts, mappings.MapToAccessKeyContract(accessKey))
}

c.JSON(http.StatusOK, accessKeyContracts)
}

// accessKeysCount will count all access keys filtered by metadata
// Access Keys Count godoc
// @Summary Access Keys Count
// @Description Access Keys Count
// @Tags Admin
// @Produce json
// @Param CountAccessKeys body filter.AdminCountAccessKeys false "Enables filtering of elements to be counted"
// @Success 200 {number} int64 "Count of access keys"
// @Failure 400 "Bad request - Error while parsing CountAccessKeys from request body"
// @Failure 500 "Internal Server Error - Error while fetching count of access keys"
// @Router /v1/admin/access-keys/count [post]
// @Security x-auth-xpub
func accessKeysCount(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
var reqParams filter.AdminCountAccessKeys
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
return
}

count, err := reqctx.Engine(c).GetAccessKeysCount(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
reqParams.Conditions.ToDbConditions(),
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
return
}

c.JSON(http.StatusOK, count)
}
86 changes: 86 additions & 0 deletions actions/admin/access_keys_old.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package admin

import (
"net/http"

"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/mappings"
"github.com/bitcoin-sv/spv-wallet/models"
"github.com/bitcoin-sv/spv-wallet/models/filter"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)

// accessKeysSearchOld will fetch a list of access keys filtered by metadata
// Access Keys Search godoc
// @DeprecatedRouter /v1/admin/access-keys/search [post]
// @Summary Access Keys Search
// @Description Access Keys Search
// @Tags Admin
// @Produce json
// @Param SearchAccessKeys body filter.AdminSearchAccessKeys false "Supports targeted resource searches with filters and metadata, plus options for pagination and sorting to streamline data exploration and analysis"
// @Success 200 {object} []models.AccessKey "List of access keys"
// @Failure 400 "Bad request - Error while parsing SearchAccessKeys from request body"
// @Failure 500 "Internal server error - Error while searching for access keys"
// @Router /v1/admin/access-keys/search [post]
// @Security x-auth-xpub
func accessKeysSearchOld(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
var reqParams filter.AdminSearchAccessKeys
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
return
}

accessKeys, err := reqctx.Engine(c).GetAccessKeys(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
reqParams.Conditions.ToDbConditions(),
mappings.MapToQueryParams(reqParams.QueryParams),
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
return
}

accessKeyContracts := make([]*models.AccessKey, 0)
for _, accessKey := range accessKeys {
accessKeyContracts = append(accessKeyContracts, mappings.MapToOldAccessKeyContract(accessKey))
}

c.JSON(http.StatusOK, accessKeyContracts)
}

// accessKeysCount will count all access keys filtered by metadata
// Access Keys Count godoc
// @DeprecatedRouter /v1/admin/access-keys/count [post]
// @Summary Access Keys Count
// @Description Access Keys Count
// @Tags Admin
// @Produce json
// @Param CountAccessKeys body filter.AdminCountAccessKeys false "Enables filtering of elements to be counted"
// @Success 200 {number} int64 "Count of access keys"
// @Failure 400 "Bad request - Error while parsing CountAccessKeys from request body"
// @Failure 500 "Internal Server Error - Error while fetching count of access keys"
// @Router /v1/admin/access-keys/count [post]
// @Security x-auth-xpub
func accessKeysCount(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
var reqParams filter.AdminCountAccessKeys
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
ac4ch marked this conversation as resolved.
Show resolved Hide resolved
return
}

count, err := reqctx.Engine(c).GetAccessKeysCount(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
reqParams.Conditions.ToDbConditions(),
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
return
}

c.JSON(http.StatusOK, count)
}
63 changes: 33 additions & 30 deletions actions/admin/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"github.com/bitcoin-sv/spv-wallet/actions/common"
"github.com/bitcoin-sv/spv-wallet/engine"
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/internal/query"
"github.com/bitcoin-sv/spv-wallet/mappings"
"github.com/bitcoin-sv/spv-wallet/models"
"github.com/bitcoin-sv/spv-wallet/models/filter"
"github.com/bitcoin-sv/spv-wallet/models/response"
"github.com/bitcoin-sv/spv-wallet/server/reqctx"
"github.com/gin-gonic/gin"
)
Expand All @@ -20,54 +21,55 @@ import (
// @Tags Admin
// @Produce json
// @Param SearchContacts body filter.SearchContacts false "Supports targeted resource searches with filters and metadata, plus options for pagination and sorting to streamline data exploration and analysis"
// @Success 200 {object} models.SearchContactsResponse "List of contacts"
// @Success 200 {object} response.PageModel[response.Contact] "List of contacts"
// @Failure 400 "Bad request - Error while parsing SearchContacts from request body"
// @Failure 500 "Internal server error - Error while searching for contacts"
// @Router /v1/admin/contact/search [post]
// @Router /api/v1/admin/contacts [get]
// @Security x-auth-xpub
func contactsSearch(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
engine := reqctx.Engine(c)
var reqParams filter.SearchContacts
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)

searchParams, err := query.ParseSearchParams[filter.ContactFilter](c)
if err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotParseQueryParams.WithTrace(err), logger)
return
}

conditions, err := reqParams.Conditions.ToDbConditions()
conditions, err := searchParams.Conditions.ToDbConditions()
if err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
spverrors.ErrorResponse(c, spverrors.ErrInvalidConditions.WithTrace(err), logger)
return
}

reqParams.DefaultsIfNil()
metadata := mappings.MapToMetadata(searchParams.Metadata)
pageOptions := mappings.MapToDbQueryParams(&searchParams.Page)

contacts, err := engine.GetContacts(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
metadata,
conditions,
mappings.MapToQueryParams(reqParams.QueryParams),
pageOptions,
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, spverrors.ErrContactsNotFound.WithTrace(err), logger)
return
}

contracts := mappings.MapToOldContactContracts(contacts)
contracts := mappings.MapToContactContracts(contacts)

count, err := engine.GetContactsCount(
c.Request.Context(),
mappings.MapToMetadata(reqParams.Metadata),
metadata,
conditions,
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, spverrors.ErrFailedToCountContacts.WithTrace(err), logger)
return
}

response := models.SearchContactsResponse{
response := response.PageModel[response.Contact]{
Content: contracts,
Page: common.GetPageFromQueryParams(reqParams.QueryParams, count),
Page: common.GetPageDescriptionFromSearchParams(pageOptions, count),
}

c.JSON(http.StatusOK, response)
Expand All @@ -81,18 +83,18 @@ func contactsSearch(c *gin.Context, _ *reqctx.AdminContext) {
// @Produce json
// @Param id path string false "Contact id"
// @Param UpdateContact body UpdateContact false "FullName and metadata to update"
// @Success 200 {object} models.Contact "Updated contact"
// @Success 200 {object} response.Contact "Updated contact"
// @Failure 400 "Bad request - Error while parsing UpdateContact from request body or getting id from path"
// @Failure 404 "Not found - Error while getting contact by id"
// @Failure 422 "Unprocessable entity - Incorrect status of contact"
// @Failure 500 "Internal server error - Error while updating contact"
// @Router /v1/admin/contact/{id} [patch]
// @Router /api/v1/admin/contacts/{id} [put]
// @Security x-auth-xpub
func contactsUpdate(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
var reqParams UpdateContact
if err := c.Bind(&reqParams); err != nil {
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest, logger)
spverrors.ErrorResponse(c, spverrors.ErrCannotBindRequest.WithTrace(err), logger)
return
}

Expand All @@ -105,7 +107,7 @@ func contactsUpdate(c *gin.Context, _ *reqctx.AdminContext) {
&reqParams.Metadata,
)
if err != nil {
spverrors.ErrorResponse(c, err, logger)
spverrors.ErrorResponse(c, spverrors.ErrUpdateContact.WithTrace(err), logger)
return
}

Expand All @@ -127,17 +129,18 @@ func contactsUpdate(c *gin.Context, _ *reqctx.AdminContext) {
// @Failure 422 "Unprocessable entity - Incorrect status of contact"
// @Failure 500 "Internal server error - Error while updating contact"
// @Failure 500 "Internal server error - Error while updating contact"
// @Router /v1/admin/contact/{id} [delete]
// @Router /api/v1/admin/contacts/{id} [delete]
// @Security x-auth-xpub
func contactsDelete(c *gin.Context, _ *reqctx.AdminContext) {
logger := reqctx.Logger(c)
id := c.Param("id")

err := reqctx.Engine(c).DeleteContactByID(
c.Request.Context(),
id,
)
if err != nil {
spverrors.ErrorResponse(c, err, reqctx.Logger(c))
spverrors.ErrorResponse(c, spverrors.ErrDeleteContact.WithTrace(err), logger)
return
}

Expand All @@ -151,13 +154,13 @@ func contactsDelete(c *gin.Context, _ *reqctx.AdminContext) {
// @Tags Admin
// @Produce json
// @Param id path string false "Contact id"
// @Success 200 {object} models.Contact "Rejected contact"
// @Success 200 {object} response.Contact "Rejected contact"
// @Failure 400 "Bad request - Error while getting id from path"
// @Failure 404 "Not found - Error while getting contact by id"
// @Failure 422 "Unprocessable entity - Incorrect status of contact"
// @Failure 500 "Internal server error - Error while updating contact"
// @Failure 500 "Internal server error - Error while changing contact status"
// @Router /v1/admin/contact/rejected/{id} [patch]
// @Router /api/v1/admin/invitations/{id} [delete]
// @Security x-auth-xpub
func contactsReject(c *gin.Context, _ *reqctx.AdminContext) {
id := c.Param("id")
Expand All @@ -168,7 +171,7 @@ func contactsReject(c *gin.Context, _ *reqctx.AdminContext) {
engine.ContactRejected,
)
if err != nil {
spverrors.ErrorResponse(c, err, reqctx.Logger(c))
spverrors.ErrorResponse(c, spverrors.ErrRejectContact.WithTrace(err), reqctx.Logger(c))
return
}

Expand All @@ -184,13 +187,13 @@ func contactsReject(c *gin.Context, _ *reqctx.AdminContext) {
// @Tags Admin
// @Produce json
// @Param id path string false "Contact id"
// @Success 200 {object} models.Contact "Changed contact"
// @Success 200 {object} response.Contact "Changed contact"
// @Failure 400 "Bad request - Error while getting id from path"
// @Failure 404 "Not found - Error while getting contact by id"
// @Failure 422 "Unprocessable entity - Incorrect status of contact"
// @Failure 500 "Internal server error - Error while updating contact"
// @Failure 500 "Internal server error - Error while changing contact status"
// @Router /v1/admin/contact/accepted/{id} [patch]
// @Router /api/v1/admin/contact/invitations/{id} [post]
// @Security x-auth-xpub
func contactsAccept(c *gin.Context, _ *reqctx.AdminContext) {
id := c.Param("id")
Expand All @@ -201,7 +204,7 @@ func contactsAccept(c *gin.Context, _ *reqctx.AdminContext) {
engine.ContactNotConfirmed,
)
if err != nil {
spverrors.ErrorResponse(c, err, reqctx.Logger(c))
spverrors.ErrorResponse(c, spverrors.ErrAcceptContact.WithTrace(err), reqctx.Logger(c))
return
}

Expand Down
Loading
Loading