+address book service
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed

This commit is contained in:
Stephan D
2025-12-01 21:20:10 +01:00
parent c4d34c5663
commit 5e1da9617f
24 changed files with 703 additions and 2 deletions

View File

@@ -7,7 +7,9 @@ import (
mongoimpl "github.com/tech/sendico/pkg/db/internal/mongo" mongoimpl "github.com/tech/sendico/pkg/db/internal/mongo"
"github.com/tech/sendico/pkg/db/invitation" "github.com/tech/sendico/pkg/db/invitation"
"github.com/tech/sendico/pkg/db/organization" "github.com/tech/sendico/pkg/db/organization"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy" "github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/db/refreshtokens" "github.com/tech/sendico/pkg/db/refreshtokens"
"github.com/tech/sendico/pkg/db/role" "github.com/tech/sendico/pkg/db/role"
"github.com/tech/sendico/pkg/db/transaction" "github.com/tech/sendico/pkg/db/transaction"
@@ -23,6 +25,8 @@ type Factory interface {
NewAccountDB() (account.DB, error) NewAccountDB() (account.DB, error)
NewOrganizationDB() (organization.DB, error) NewOrganizationDB() (organization.DB, error)
NewInvitationsDB() (invitation.DB, error) NewInvitationsDB() (invitation.DB, error)
NewRecipientsDB() (recipient.DB, error)
NewPaymentMethodsDB() (paymethod.DB, error)
NewRolesDB() (role.DB, error) NewRolesDB() (role.DB, error)
NewPoliciesDB() (policy.DB, error) NewPoliciesDB() (policy.DB, error)

View File

@@ -15,13 +15,17 @@ import (
"github.com/tech/sendico/pkg/db/internal/mongo/confirmationdb" "github.com/tech/sendico/pkg/db/internal/mongo/confirmationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/invitationdb" "github.com/tech/sendico/pkg/db/internal/mongo/invitationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/organizationdb" "github.com/tech/sendico/pkg/db/internal/mongo/organizationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/paymethoddb"
"github.com/tech/sendico/pkg/db/internal/mongo/policiesdb" "github.com/tech/sendico/pkg/db/internal/mongo/policiesdb"
"github.com/tech/sendico/pkg/db/internal/mongo/recipientdb"
"github.com/tech/sendico/pkg/db/internal/mongo/refreshtokensdb" "github.com/tech/sendico/pkg/db/internal/mongo/refreshtokensdb"
"github.com/tech/sendico/pkg/db/internal/mongo/rolesdb" "github.com/tech/sendico/pkg/db/internal/mongo/rolesdb"
"github.com/tech/sendico/pkg/db/internal/mongo/transactionimp" "github.com/tech/sendico/pkg/db/internal/mongo/transactionimp"
"github.com/tech/sendico/pkg/db/invitation" "github.com/tech/sendico/pkg/db/invitation"
"github.com/tech/sendico/pkg/db/organization" "github.com/tech/sendico/pkg/db/organization"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy" "github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/db/refreshtokens" "github.com/tech/sendico/pkg/db/refreshtokens"
"github.com/tech/sendico/pkg/db/repository" "github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/db/role" "github.com/tech/sendico/pkg/db/role"
@@ -201,6 +205,29 @@ func (db *DB) NewOrganizationDB() (organization.DB, error) {
return organizationDB, nil return organizationDB, nil
} }
func (db *DB) NewRecipientsDB() (recipient.DB, error) {
pmdb, err := db.NewPaymentMethodsDB()
if err != nil {
db.logger.Warn("Failed to create payment methods database", zap.Error(err))
return nil, err
}
create := func(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
db *mongo.Database,
) (recipient.DB, error) {
return recipientdb.Create(ctx, logger, enforcer, pdb, pmdb, db)
}
return newProtectedDB(db, create)
}
func (db *DB) NewPaymentMethodsDB() (paymethod.DB, error) {
return newProtectedDB(db, paymethoddb.Create)
}
func (db *DB) NewRefreshTokensDB() (refreshtokens.DB, error) { func (db *DB) NewRefreshTokensDB() (refreshtokens.DB, error) {
return refreshtokensdb.Create(db.logger, db.db()) return refreshtokensdb.Create(db.logger, db.db())
} }

View File

@@ -0,0 +1,20 @@
package paymethoddb
import (
"context"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func (db *PaymentMethodsDB) SetArchived(ctx context.Context, accountRef, organizationRef, objectRef primitive.ObjectID, isArchived, cascade bool) error {
// Use the ArchivableDB for the main archiving logic
if err := db.ArchivableDB.SetArchived(ctx, accountRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to chnage object archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("object_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
return nil
}

View File

@@ -0,0 +1,49 @@
package paymethoddb
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/mongo"
)
type PaymentMethodsDB struct {
auth.ProtectedDBImp[*model.PaymentMethod]
auth.ArchivableDB[*model.PaymentMethod]
}
func Create(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
db *mongo.Database,
) (*PaymentMethodsDB, error) {
p, err := auth.CreateDBImp[*model.PaymentMethod](ctx, logger, pdb, enforcer, mservice.PaymentMethods, db)
if err != nil {
return nil, err
}
createEmpty := func() *model.PaymentMethod {
return &model.PaymentMethod{}
}
getArchivable := func(c *model.PaymentMethod) model.Archivable {
return &c.ArchivableBase
}
res := &PaymentMethodsDB{
ProtectedDBImp: *p,
ArchivableDB: auth.NewArchivableDB(
p.DBImp,
logger,
p.Enforcer,
createEmpty,
getArchivable,
),
}
return res, nil
}

View File

@@ -0,0 +1,28 @@
package paymethoddb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
mauth "github.com/tech/sendico/pkg/mutil/db/auth"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (db *PaymentMethodsDB) List(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, cursor *model.ViewCursor) ([]model.PaymentMethod, error) {
res, err := mauth.GetProtectedObjects[model.PaymentMethod](
ctx,
db.DBImp.Logger,
accountRef, organizationRef, model.ActionRead,
repository.OrgFilter(organizationRef).And(repository.Filter("recipientRef", recipientRef)),
cursor,
db.Enforcer,
db.DBImp.Repository,
)
if errors.Is(err, merrors.ErrNoData) {
return []model.PaymentMethod{}, nil
}
return res, err
}

View File

@@ -0,0 +1,57 @@
package recipientdb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func (db *RecipientDB) SetArchived(ctx context.Context, accountRef, organizationRef, objectRef primitive.ObjectID, isArchived, cascade bool) error {
// Use the ArchivableDB for the main archiving logic
if err := db.ArchivableDB.SetArchived(ctx, accountRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to change recipient archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("recipient_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
if cascade {
if err := db.setArchivedPaymentMethods(ctx, accountRef, organizationRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to update payment methods archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("recipient_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
}
return nil
}
func (db *RecipientDB) setArchivedPaymentMethods(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, archived bool) error {
db.DBImp.Logger.Debug("Setting archived status for recipient payment methods", mzap.ObjRef("recipient_ref", recipientRef), zap.Bool("archived", archived))
db.DBImp.Logger.Debug("Applying archived status to payment methods for recipient", mzap.ObjRef("recipient_ref", recipientRef))
// Get all payMethods for the recipient
payMethods, err := db.pmdb.List(ctx, accountRef, organizationRef, recipientRef, nil)
if err != nil && !errors.Is(err, merrors.ErrNoData) {
db.DBImp.Logger.Warn("Failed to fetch payment methods for recipient", zap.Error(err), mzap.ObjRef("recipient_ref", recipientRef))
return err
}
// Archive each payment method
for _, pmethod := range payMethods {
if err := db.pmdb.SetArchived(ctx, accountRef, organizationRef, pmethod.ID, archived, true); err != nil {
db.DBImp.Logger.Warn("Failed to set archived status for payment method", zap.Error(err), mzap.ObjRef("payment_method_ref", pmethod.ID))
return err
}
}
db.DBImp.Logger.Debug("Successfully updated payment methods archived status", zap.Int("count", len(payMethods)), mzap.ObjRef("recipient_ref", recipientRef))
return nil
}

View File

@@ -0,0 +1,56 @@
package recipientdb
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/mongo"
)
type RecipientDB struct {
auth.ProtectedDBImp[*model.Recipient]
auth.ArchivableDB[*model.Recipient]
pmdb paymethod.DB
paymentMethodsRepo repository.Repository
}
func Create(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
pmdb paymethod.DB,
db *mongo.Database,
) (*RecipientDB, error) {
p, err := auth.CreateDBImp[*model.Recipient](ctx, logger, pdb, enforcer, mservice.Organizations, db)
if err != nil {
return nil, err
}
createEmpty := func() *model.Recipient {
return &model.Recipient{}
}
getArchivable := func(c *model.Recipient) model.Archivable {
return &c.ArchivableBase
}
res := &RecipientDB{
ProtectedDBImp: *p,
ArchivableDB: auth.NewArchivableDB(
p.DBImp,
p.DBImp.Logger,
enforcer,
createEmpty,
getArchivable,
),
paymentMethodsRepo: repository.CreateMongoRepository(db, string(mservice.PaymentMethods)),
pmdb: pmdb,
}
return res, nil
}

View File

@@ -0,0 +1,28 @@
package recipientdb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
mauth "github.com/tech/sendico/pkg/mutil/db/auth"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (db *RecipientDB) List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Recipient, error) {
res, err := mauth.GetProtectedObjects[model.Recipient](
ctx,
db.DBImp.Logger,
accountRef, organizationRef, model.ActionRead,
repository.OrgFilter(organizationRef),
cursor,
db.Enforcer,
db.DBImp.Repository,
)
if errors.Is(err, merrors.ErrNoData) {
return []model.Recipient{}, nil
}
return res, err
}

View File

@@ -15,5 +15,5 @@ type DB interface {
Decline(ctx context.Context, invitationRef primitive.ObjectID) error Decline(ctx context.Context, invitationRef primitive.ObjectID) error
List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Invitation, error) List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Invitation, error)
DeleteCascade(ctx context.Context, accountRef, statusRef primitive.ObjectID) error DeleteCascade(ctx context.Context, accountRef, statusRef primitive.ObjectID) error
SetArchived(ctx context.Context, accountRef, organizationRef, statusRef primitive.ObjectID, archived, cascade bool) error SetArchived(ctx context.Context, accountRef, organizationRef, invitationRef primitive.ObjectID, archived, cascade bool) error
} }

View File

@@ -0,0 +1,15 @@
package paymethod
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type DB interface {
auth.ProtectedDB[*model.PaymentMethod]
SetArchived(ctx context.Context, accountRef, organizationRef, methodRef primitive.ObjectID, archived, cascade bool) error
List(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, cursor *model.ViewCursor) ([]model.PaymentMethod, error)
}

View File

@@ -0,0 +1,15 @@
package recipient
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type DB interface {
auth.ProtectedDB[*model.Recipient]
SetArchived(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, archived, cascade bool) error
List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Recipient, error)
}

25
api/pkg/model/card.go Normal file
View File

@@ -0,0 +1,25 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type CardPaymentData struct {
Pan string `bson:"pan" json:"pan"`
FirstName string `bson:"firstName" json:"firstName"`
LastName string `bson:"lastName" json:"lastName"`
}
func (m *PaymentMethod) AsCard() (*CardPaymentData, error) {
if m.Type != PaymentTypeCard {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not card", m.Type), "type")
}
var d CardPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

26
api/pkg/model/iban.go Normal file
View File

@@ -0,0 +1,26 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type IbanPaymentData struct {
Iban string `bson:"iban" json:"iban"`
AccountHolder string `bson:"accountHolder" json:"accountHolder"`
Bic *string `bson:"bic,omitempty" json:"bic,omitempty"`
BankName *string `bson:"bankName,omitempty" json:"bankName,omitempty"`
}
func (m *PaymentMethod) AsIban() (*IbanPaymentData, error) {
if m.Type != PaymentTypeIban {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not iban", m.Type), "type")
}
var d IbanPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

66
api/pkg/model/payment.go Normal file
View File

@@ -0,0 +1,66 @@
package model
import (
"encoding/json"
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type PaymentType int
const (
PaymentTypeIban PaymentType = iota
PaymentTypeCard
PaymentTypeBankAccount
PaymentTypeWallet
)
var paymentTypeToString = map[PaymentType]string{
PaymentTypeIban: "iban",
PaymentTypeCard: "card",
PaymentTypeBankAccount: "bankAccount",
PaymentTypeWallet: "wallet",
}
var paymentTypeFromString = map[string]PaymentType{
"iban": PaymentTypeIban,
"card": PaymentTypeCard,
"bankAccount": PaymentTypeBankAccount,
"wallet": PaymentTypeWallet,
}
func (t PaymentType) String() string {
if v, ok := paymentTypeToString[t]; ok {
return v
}
return "iban"
}
func (t PaymentType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *PaymentType) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := paymentTypeFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown PaymentType: %q", val))
}
*t = v
return nil
}
type PaymentMethod struct {
PermissionBound `bson:",inline" json:",inline"`
RecipientRef primitive.ObjectID `bson:"recipientRef" json:"recipientRef"`
Type PaymentType `bson:"type" json:"type"`
IsActive bool `bson:"isActive" json:"isActive"`
Data bson.Raw `bson:"data" json:"data"`
}

31
api/pkg/model/rba.go Normal file
View File

@@ -0,0 +1,31 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type RussianBankAccountPaymentData struct {
RecipientName string `bson:"recipientName" json:"recipientName"`
Inn string `bson:"inn" json:"inn"`
Kpp string `bson:"kpp" json:"kpp"`
BankName string `bson:"bankName" json:"bankName"`
Bik string `bson:"bik" json:"bik"`
AccountNumber string `bson:"accountNumber" json:"accountNumber"`
CorrespondentAccount string `bson:"correspondentAccount" json:"correspondentAccount"`
}
func (m *PaymentMethod) AsRussianBankAccount() (*RussianBankAccountPaymentData, error) {
if m.Type != PaymentTypeBankAccount {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not bankAccount", m.Type), "type")
}
var d RussianBankAccountPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

106
api/pkg/model/recipient.go Normal file
View File

@@ -0,0 +1,106 @@
package model
import (
"encoding/json"
"fmt"
"github.com/tech/sendico/pkg/merrors"
)
type RecipientStatus int
const (
RecipientStatusReady RecipientStatus = iota
RecipientStatusRegistered
RecipientStatusNotRegistered
)
var recipientStatusToString = map[RecipientStatus]string{
RecipientStatusReady: "ready",
RecipientStatusRegistered: "registered",
RecipientStatusNotRegistered: "notRegistered",
}
var recipientStatusFromString = map[string]RecipientStatus{
"ready": RecipientStatusReady,
"registered": RecipientStatusRegistered,
"notRegistered": RecipientStatusNotRegistered,
}
func (s RecipientStatus) String() string {
if v, ok := recipientStatusToString[s]; ok {
return v
}
return "ready" // дефолт, можно поменять
}
// JSON: храним как строку ("ready" / "registered" / "notRegistered")
func (s RecipientStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
func (s *RecipientStatus) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := recipientStatusFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientStatus: %q", val))
}
*s = v
return nil
}
// RecipientType { internal, external }
type RecipientType int
const (
RecipientTypeInternal RecipientType = iota
RecipientTypeExternal
)
var recipientTypeToString = map[RecipientType]string{
RecipientTypeInternal: "internal",
RecipientTypeExternal: "external",
}
var recipientTypeFromString = map[string]RecipientType{
"internal": RecipientTypeInternal,
"external": RecipientTypeExternal,
}
func (t RecipientType) String() string {
if v, ok := recipientTypeToString[t]; ok {
return v
}
return "internal"
}
func (t RecipientType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *RecipientType) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := recipientTypeFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientType: %q", val))
}
*t = v
return nil
}
type Recipient struct {
PermissionBound `bson:",inline" json:",inline"`
Describable `bson:",inline" json:",inline"`
Email string `bson:"email" json:"email"`
AvatarURL *string `bson:"avatarUrl,omitempty" json:"avatarUrl,omitempty"`
Status RecipientStatus `bson:"status" json:"status"`
Type RecipientType `bson:"type" json:"type"`
}

25
api/pkg/model/wallet.go Normal file
View File

@@ -0,0 +1,25 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type WalletPaymentData struct {
WalletID string `bson:"walletId" json:"walletId"`
}
func (m *PaymentMethod) AsWallet() (*WalletPaymentData, error) {
if m.Type != PaymentTypeWallet {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not wallet", m.Type), "type")
}
var d WalletPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

View File

@@ -33,9 +33,11 @@ const (
Notifications Type = "notifications" // Represents notifications sent to users Notifications Type = "notifications" // Represents notifications sent to users
Organizations Type = "organizations" // Represents organizations in the system Organizations Type = "organizations" // Represents organizations in the system
Payments Type = "payments" // Represents payments service Payments Type = "payments" // Represents payments service
PaymentMethods Type = "payment_methods" // Represents payment methods service
Permissions Type = "permissions" // Represents permissiosns service Permissions Type = "permissions" // Represents permissiosns service
Policies Type = "policies" // Represents access control policies Policies Type = "policies" // Represents access control policies
PolicyAssignements Type = "policy_assignments" // Represents policy assignments database PolicyAssignements Type = "policy_assignments" // Represents policy assignments database
Recipients Type = "recipients" // Represents payment recipients
RefreshTokens Type = "refresh_tokens" // Represents refresh tokens for authentication RefreshTokens Type = "refresh_tokens" // Represents refresh tokens for authentication
Roles Type = "roles" // Represents roles in access control Roles Type = "roles" // Represents roles in access control
Storage Type = "storage" // Represents statuses of tasks or projects Storage Type = "storage" // Represents statuses of tasks or projects

View File

@@ -0,0 +1,11 @@
package paymethod
import (
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/paymethodsimp"
)
func Create(a api.API) (mservice.MicroService, error) {
return paymethodsimp.CreateAPI(a)
}

View File

@@ -0,0 +1,11 @@
package recipient
import (
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/server/interface/api"
recipientimp "github.com/tech/sendico/server/internal/server/paymethodsimp"
)
func Create(a api.API) (mservice.MicroService, error) {
return recipientimp.CreateAPI(a)
}

View File

@@ -14,12 +14,14 @@ import (
"github.com/tech/sendico/server/interface/services/account" "github.com/tech/sendico/server/interface/services/account"
"github.com/tech/sendico/server/interface/services/confirmation" "github.com/tech/sendico/server/interface/services/confirmation"
"github.com/tech/sendico/server/interface/services/invitation" "github.com/tech/sendico/server/interface/services/invitation"
"github.com/tech/sendico/server/interface/services/ledger"
"github.com/tech/sendico/server/interface/services/logo" "github.com/tech/sendico/server/interface/services/logo"
"github.com/tech/sendico/server/interface/services/organization" "github.com/tech/sendico/server/interface/services/organization"
"github.com/tech/sendico/server/interface/services/paymethod"
"github.com/tech/sendico/server/interface/services/permission" "github.com/tech/sendico/server/interface/services/permission"
"github.com/tech/sendico/server/interface/services/recipient"
"github.com/tech/sendico/server/interface/services/site" "github.com/tech/sendico/server/interface/services/site"
"github.com/tech/sendico/server/interface/services/wallet" "github.com/tech/sendico/server/interface/services/wallet"
"github.com/tech/sendico/server/interface/services/ledger"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -87,6 +89,8 @@ func (a *APIImp) installServices() error {
srvf = append(srvf, site.Create) srvf = append(srvf, site.Create)
srvf = append(srvf, wallet.Create) srvf = append(srvf, wallet.Create)
srvf = append(srvf, ledger.Create) srvf = append(srvf, ledger.Create)
srvf = append(srvf, recipient.Create)
srvf = append(srvf, paymethod.Create)
for _, v := range srvf { for _, v := range srvf {
if err := a.addMicroservice(v); err != nil { if err := a.addMicroservice(v); err != nil {

View File

@@ -0,0 +1,46 @@
package paymethodsimp
import (
"context"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
eapi "github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/papitemplate"
"go.uber.org/zap"
)
type RecipientAPI struct {
papitemplate.ProtectedAPI[model.PaymentMethod]
db paymethod.DB
}
func (a *RecipientAPI) Name() mservice.Type {
return mservice.Recipients
}
func (a *RecipientAPI) Finish(_ context.Context) error {
return nil
}
func CreateAPI(a eapi.API) (*RecipientAPI, error) {
dbFactory := func() (papitemplate.ProtectedDB[model.PaymentMethod], error) {
return a.DBFactory().NewPaymentMethodsDB()
}
res := &RecipientAPI{}
p, err := papitemplate.CreateAPI(a, dbFactory, mservice.Recipients, mservice.PaymentMethods)
if err != nil {
return nil, err
}
res.ProtectedAPI = *p.Build()
if res.db, err = a.DBFactory().NewPaymentMethodsDB(); err != nil {
res.Logger.Warn("Failed to create payment methods database", zap.Error(err))
return nil, err
}
return res, nil
}

View File

@@ -0,0 +1,46 @@
package recipientimp
import (
"context"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
eapi "github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/papitemplate"
"go.uber.org/zap"
)
type RecipientAPI struct {
papitemplate.ProtectedAPI[model.Recipient]
db recipient.DB
}
func (a *RecipientAPI) Name() mservice.Type {
return mservice.Recipients
}
func (a *RecipientAPI) Finish(_ context.Context) error {
return nil
}
func CreateAPI(a eapi.API) (*RecipientAPI, error) {
dbFactory := func() (papitemplate.ProtectedDB[model.Recipient], error) {
return a.DBFactory().NewRecipientsDB()
}
res := &RecipientAPI{}
p, err := papitemplate.CreateAPI(a, dbFactory, mservice.Organizations, mservice.Recipients)
if err != nil {
return nil, err
}
res.ProtectedAPI = *p.Build()
if res.db, err = a.DBFactory().NewRecipientsDB(); err != nil {
res.Logger.Warn("Failed to create recipients database", zap.Error(err))
return nil, err
}
return res, nil
}

View File

@@ -9,6 +9,9 @@ class Services {
static const String storage = 'storage'; static const String storage = 'storage';
static const String chainWallets = 'chain_wallets'; static const String chainWallets = 'chain_wallets';
static const String recipients = 'recipients';
static const String paymentMethods = 'payment_methods';
static const String amplitude = 'amplitude'; static const String amplitude = 'amplitude';
static const String clients = 'clients'; static const String clients = 'clients';
static const String logo = 'logo'; static const String logo = 'logo';