76 lines
2.9 KiB
Go
76 lines
2.9 KiB
Go
package grpcadapter
|
|
|
|
import (
|
|
"context"
|
|
"crypto/subtle"
|
|
domain "gl/domain/ledger"
|
|
basev1 "gl/gen/base/v1"
|
|
ledgerv1 "gl/gen/ledger/v1"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/metadata"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
func (h *Handler) requireAdmin(ctx context.Context) error {
|
|
values := metadata.ValueFromIncomingContext(ctx, "x-admin-token")
|
|
if h.adminToken == "" || len(values) != 1 || subtle.ConstantTimeCompare([]byte(values[0]), []byte(h.adminToken)) != 1 {
|
|
return status.Error(codes.PermissionDenied, "invalid administrative token")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func modeMessage(state domain.OperatingState) *ledgerv1.OperatingModeResponse {
|
|
return &ledgerv1.OperatingModeResponse{Mode: string(state.Mode), Revision: state.Revision, ActorId: state.ActorID, Reason: state.Reason, ChangedAt: timestampMessage(state.ChangedAt)}
|
|
}
|
|
|
|
func (h *Handler) GetOperatingMode(ctx context.Context, _ *basev1.Empty) (*ledgerv1.OperatingModeResponse, error) {
|
|
state, err := h.ledger.OperatingMode(ctx)
|
|
if err != nil {
|
|
return nil, rpcError(err)
|
|
}
|
|
return modeMessage(state), nil
|
|
}
|
|
|
|
func (h *Handler) SetOperatingMode(ctx context.Context, request *ledgerv1.SetOperatingModeRequest) (*ledgerv1.OperatingModeResponse, error) {
|
|
if err := h.requireAdmin(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
state, err := h.ledger.SetOperatingMode(ctx, domain.OperatingMode(request.GetMode()), request.GetExpectedRevision(), request.GetActorId(), request.GetReason(), request.GetReconciliationConfirmed())
|
|
if err != nil {
|
|
return nil, rpcError(err)
|
|
}
|
|
return modeMessage(state), nil
|
|
}
|
|
|
|
func (h *Handler) PostInternalJournal(ctx context.Context, request *ledgerv1.AppendJournalRequest) (*ledgerv1.AppendJournalResponse, error) {
|
|
if err := h.requireAdmin(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
command, err := appendJournalCommand(request)
|
|
if err != nil {
|
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
}
|
|
result, err := h.ledger.PostInternalJournal(ctx, command)
|
|
if err != nil {
|
|
return nil, rpcError(err)
|
|
}
|
|
return &ledgerv1.AppendJournalResponse{Journal: journalMessage(result.Journal), AlreadyExisted: result.AlreadyExisted}, nil
|
|
}
|
|
|
|
func (h *Handler) GetUserBalances(ctx context.Context, request *ledgerv1.GetUserBalancesRequest) (*ledgerv1.GetUserBalancesResponse, error) {
|
|
if request == nil {
|
|
return nil, status.Error(codes.InvalidArgument, "request is required")
|
|
}
|
|
balances, err := h.ledger.UserBalances(ctx, request.GetOwnerType(), request.GetOwnerId(), request.AssetId)
|
|
if err != nil {
|
|
return nil, rpcError(err)
|
|
}
|
|
response := &ledgerv1.GetUserBalancesResponse{OwnerType: request.GetOwnerType(), OwnerId: request.GetOwnerId()}
|
|
for _, balance := range balances {
|
|
response.Balances = append(response.Balances, &ledgerv1.UserAssetBalance{
|
|
AssetId: balance.AssetID, Available: balance.Available.String(), Frozen: balance.Frozen.String(), Total: balance.Available.Add(balance.Frozen).String(),
|
|
})
|
|
}
|
|
return response, nil
|
|
}
|