Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
5 changes: 3 additions & 2 deletions XMRpos-backend/internal/core/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ func NewRouter(ctx context.Context, cfg *config.Config, db *gorm.DB, rpcClient *
miscRepository := misc.NewMiscRepository(db)

// Initialize services
adminService := admin.NewAdminService(adminRepository, cfg)
authService := auth.NewAuthService(authRepository, cfg)
vendorService := vendor.NewVendorService(vendorRepository, db, cfg, rpcClient, moneroPayClient)
vendorService.StartTransferCompleter(ctx, 30*time.Second) // Check every 30 seconds
adminService := admin.NewAdminService(adminRepository, cfg, vendorService)
authService := auth.NewAuthService(authRepository, cfg)
posService := pos.NewPosService(posRepository, cfg, moneroPayClient)
callbackService := callback.NewCallbackService(callbackRepository, cfg, moneroPayClient)
callbackService.StartConfirmationChecker(ctx, 2*time.Second) // Check for confirmations every 2 seconds
Expand Down Expand Up @@ -102,6 +102,7 @@ func NewRouter(ctx context.Context, cfg *config.Config, db *gorm.DB, rpcClient *
r.Get("/admin/vendors", adminHandler.ListVendors)
r.Get("/admin/balance", adminHandler.GetWalletBalance)
r.Post("/admin/transfer-balance", adminHandler.TransferBalance)
r.Post("/admin/delete", adminHandler.DeleteVendor)

// Vendor routes
r.Post("/vendor/delete", vendorHandler.DeleteVendor)
Expand Down
65 changes: 65 additions & 0 deletions XMRpos-backend/internal/features/admin/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ type transferBalanceRequest struct {
VendorID uint `json:"vendor_id"`
}

type deleteVendorRequest struct {
VendorID uint `json:"vendor_id"`
}

type deleteVendorResponse struct {
Success bool `json:"success"`
ID uint `json:"id"`
}

func (h *AdminHandler) CreateInvite(w http.ResponseWriter, r *http.Request) {
// check jwt if admin

Expand Down Expand Up @@ -182,3 +191,59 @@ func (h *AdminHandler) TransferBalance(w http.ResponseWriter, r *http.Request) {
io.Copy(io.Discard, r.Body)
}

func (h *AdminHandler) DeleteVendor(w http.ResponseWriter, r *http.Request) {
role, ok := utils.GetClaimFromContext(r.Context(), models.ClaimsRoleKey)
if !ok || role != "admin" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}

ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
r = r.WithContext(ctx)
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)

var req deleteVendorRequest
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
if err := dec.Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}

if req.VendorID == 0 {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]any{
"success": false,
"message": "vendor_id is required",
})
io.Copy(io.Discard, r.Body)
return
}

httpErr := h.service.DeleteVendor(ctx, req.VendorID)
if httpErr != nil {
message := httpErr.Message
if httpErr.Code == http.StatusNotFound {
message = "No vendor with ID"
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(httpErr.Code)
_ = json.NewEncoder(w).Encode(map[string]any{
"success": false,
"message": message,
})
io.Copy(io.Discard, r.Body)
return
}

resp := deleteVendorResponse{
Success: true,
ID: req.VendorID,
}

w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
io.Copy(io.Discard, r.Body)
}
29 changes: 24 additions & 5 deletions XMRpos-backend/internal/features/admin/service.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package admin

import (
"time"
"context"
"net/http"
"time"

gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/monerokon/xmrpos/xmrpos-backend/internal/core/config"
"github.com/monerokon/xmrpos/xmrpos-backend/internal/core/models"
vendorfeature "github.com/monerokon/xmrpos/xmrpos-backend/internal/features/vendor"
)

type AdminService struct {
repo AdminRepository
config *config.Config
repo AdminRepository
config *config.Config
vendorService *vendorfeature.VendorService
}

type VendorSummary struct {
Expand All @@ -21,8 +24,8 @@ type VendorSummary struct {
Balance int64 `json:"balance"`
}

func NewAdminService(repo AdminRepository, cfg *config.Config) *AdminService {
return &AdminService{repo: repo, config: cfg}
func NewAdminService(repo AdminRepository, cfg *config.Config, vendorService *vendorfeature.VendorService) *AdminService {
return &AdminService{repo: repo, config: cfg, vendorService: vendorService}
}

func (s *AdminService) CreateInvite(ctx context.Context, validUntil time.Time, forcedName *string) (inviteCode string, err error) {
Expand Down Expand Up @@ -58,3 +61,19 @@ func (s *AdminService) ListVendorsWithBalances(ctx context.Context) ([]VendorSum

return s.repo.ListVendorsWithBalances(ctx)
}

func (s *AdminService) DeleteVendor(ctx context.Context, vendorID uint) (httpErr *models.HTTPError) {
if ctx == nil {
ctx = context.Background()
}

if s.vendorService == nil {
return models.NewHTTPError(http.StatusInternalServerError, "vendor service not configured")
}

if vendorID == 0 {
return models.NewHTTPError(http.StatusBadRequest, "vendor_id is required")
}

return s.vendorService.DeleteVendor(ctx, vendorID)
}