mirror of
https://github.com/emo2007/block-accounting.git
synced 2025-04-12 08:56:28 +00:00
jtx
This commit is contained in:
parent
a482e9d3f3
commit
36daecdd25
3
backend/.vscode/launch.json
vendored
3
backend/.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "debug",
|
"name": "blockd",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
@ -14,6 +14,7 @@
|
|||||||
"-log-level=debug",
|
"-log-level=debug",
|
||||||
"-log-local=true",
|
"-log-local=true",
|
||||||
"-log-add-source=true",
|
"-log-add-source=true",
|
||||||
|
"-jwt-secret=local_jwt_secret",
|
||||||
|
|
||||||
"-rest-address=localhost:8080",
|
"-rest-address=localhost:8080",
|
||||||
"-db-host=localhost:8432",
|
"-db-host=localhost:8432",
|
||||||
|
@ -30,7 +30,8 @@ run.local: bin.build
|
|||||||
-db-database=blockd \
|
-db-database=blockd \
|
||||||
-db-user=blockd \
|
-db-user=blockd \
|
||||||
-db-secret=blockd \
|
-db-secret=blockd \
|
||||||
-db-enable-tls=false
|
-db-enable-tls=false \
|
||||||
|
-jwt-secret=local_jwt_secret
|
||||||
|
|
||||||
.PHONY: run.debug
|
.PHONY: run.debug
|
||||||
run.debug: bin.build
|
run.debug: bin.build
|
||||||
|
@ -34,6 +34,9 @@ func main() {
|
|||||||
Name: "log-add-source",
|
Name: "log-add-source",
|
||||||
Value: true,
|
Value: true,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "jwt-secret",
|
||||||
|
},
|
||||||
|
|
||||||
// rest
|
// rest
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
@ -77,6 +80,7 @@ func main() {
|
|||||||
LogLocal: c.Bool("log-local"),
|
LogLocal: c.Bool("log-local"),
|
||||||
LogFile: c.String("log-file"),
|
LogFile: c.String("log-file"),
|
||||||
LogAddSource: c.Bool("log-add-source"),
|
LogAddSource: c.Bool("log-add-source"),
|
||||||
|
JWTSecret: []byte(c.String("jwt-secret")),
|
||||||
},
|
},
|
||||||
Rest: config.RestConfig{
|
Rest: config.RestConfig{
|
||||||
Address: c.String("rest-address"),
|
Address: c.String("rest-address"),
|
||||||
|
21
backend/internal/factory/interactors.go
Normal file
21
backend/internal/factory/interactors.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/emochka2007/block-accounting/internal/pkg/config"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||||
|
urepo "github.com/emochka2007/block-accounting/internal/usecase/repository/users"
|
||||||
|
)
|
||||||
|
|
||||||
|
func provideUsersInteractor(
|
||||||
|
log *slog.Logger,
|
||||||
|
usersRepo urepo.Repository,
|
||||||
|
) users.UsersInteractor {
|
||||||
|
return users.NewUsersInteractor(log.WithGroup("users-interactor"), usersRepo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func provideJWTInteractor(c config.Config) jwt.JWTInteractor {
|
||||||
|
return jwt.NewWardenJWT(c.Common.JWTSecret)
|
||||||
|
}
|
@ -4,13 +4,22 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/google/wire"
|
||||||
|
|
||||||
"github.com/emochka2007/block-accounting/internal/interface/rest"
|
"github.com/emochka2007/block-accounting/internal/interface/rest"
|
||||||
"github.com/emochka2007/block-accounting/internal/interface/rest/controllers"
|
"github.com/emochka2007/block-accounting/internal/interface/rest/controllers"
|
||||||
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
|
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
|
||||||
"github.com/emochka2007/block-accounting/internal/pkg/config"
|
"github.com/emochka2007/block-accounting/internal/pkg/config"
|
||||||
"github.com/emochka2007/block-accounting/internal/pkg/logger"
|
"github.com/emochka2007/block-accounting/internal/pkg/logger"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||||
urepo "github.com/emochka2007/block-accounting/internal/usecase/repository/users"
|
)
|
||||||
|
|
||||||
|
var interfaceSet wire.ProviderSet = wire.NewSet(
|
||||||
|
provideAuthController,
|
||||||
|
provideControllers,
|
||||||
|
|
||||||
|
provideAuthPresenter,
|
||||||
)
|
)
|
||||||
|
|
||||||
func provideLogger(c config.Config) *slog.Logger {
|
func provideLogger(c config.Config) *slog.Logger {
|
||||||
@ -36,20 +45,31 @@ func provideLogger(c config.Config) *slog.Logger {
|
|||||||
return lb.Build()
|
return lb.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func provideAuthPresenter(
|
||||||
|
jwtInteractor jwt.JWTInteractor,
|
||||||
|
) presenters.AuthPresenter {
|
||||||
|
return presenters.NewAuthPresenter(jwtInteractor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func provideAuthController(
|
||||||
|
log *slog.Logger,
|
||||||
|
usersInteractor users.UsersInteractor,
|
||||||
|
authPresenter presenters.AuthPresenter,
|
||||||
|
) controllers.AuthController {
|
||||||
|
return controllers.NewAuthController(
|
||||||
|
log.WithGroup("auth-controller"),
|
||||||
|
authPresenter,
|
||||||
|
usersInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func provideControllers(
|
func provideControllers(
|
||||||
log *slog.Logger,
|
log *slog.Logger,
|
||||||
usersRepo urepo.Repository,
|
authController controllers.AuthController,
|
||||||
) *controllers.RootController {
|
) *controllers.RootController {
|
||||||
return &controllers.RootController{
|
return &controllers.RootController{
|
||||||
Ping: controllers.NewPingController(log.WithGroup("ping-controller")),
|
Ping: controllers.NewPingController(log.WithGroup("ping-controller")),
|
||||||
Auth: controllers.NewAuthController(
|
Auth: authController,
|
||||||
log.WithGroup("auth-controller"),
|
|
||||||
presenters.NewAuthPresenter(),
|
|
||||||
users.NewUsersInteractor(
|
|
||||||
log.WithGroup("users-interactor"),
|
|
||||||
usersRepo,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,11 @@ import (
|
|||||||
|
|
||||||
func ProvideService(c config.Config) (service.Service, func(), error) {
|
func ProvideService(c config.Config) (service.Service, func(), error) {
|
||||||
wire.Build(
|
wire.Build(
|
||||||
provideUsersRepository,
|
|
||||||
provideLogger,
|
provideLogger,
|
||||||
provideControllers,
|
provideUsersRepository,
|
||||||
|
provideUsersInteractor,
|
||||||
|
provideJWTInteractor,
|
||||||
|
interfaceSet,
|
||||||
provideRestServer,
|
provideRestServer,
|
||||||
service.NewService,
|
service.NewService,
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,11 @@ func ProvideService(c config.Config) (service.Service, func(), error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
rootController := provideControllers(logger, repository)
|
usersInteractor := provideUsersInteractor(logger, repository)
|
||||||
|
jwtInteractor := provideJWTInteractor(c)
|
||||||
|
authPresenter := provideAuthPresenter(jwtInteractor)
|
||||||
|
authController := provideAuthController(logger, usersInteractor, authPresenter)
|
||||||
|
rootController := provideControllers(logger, authController)
|
||||||
server := provideRestServer(logger, rootController, c)
|
server := provideRestServer(logger, rootController, c)
|
||||||
serviceService := service.NewService(logger, server)
|
serviceService := service.NewService(logger, server)
|
||||||
return serviceService, func() {
|
return serviceService, func() {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
|
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
|
||||||
"github.com/emochka2007/block-accounting/internal/pkg/bip32"
|
"github.com/emochka2007/block-accounting/internal/pkg/bip32"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ type authController struct {
|
|||||||
log *slog.Logger
|
log *slog.Logger
|
||||||
presenter presenters.AuthPresenter
|
presenter presenters.AuthPresenter
|
||||||
usersInteractor users.UsersInteractor
|
usersInteractor users.UsersInteractor
|
||||||
|
jwtInteractor jwt.JWTInteractor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthController(
|
func NewAuthController(
|
||||||
@ -45,27 +47,32 @@ func NewAuthController(
|
|||||||
func (c *authController) Join(w http.ResponseWriter, req *http.Request) error {
|
func (c *authController) Join(w http.ResponseWriter, req *http.Request) error {
|
||||||
request, err := c.presenter.CreateJoinRequest(req)
|
request, err := c.presenter.CreateJoinRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error create join request. %w", err)
|
return c.presenter.ResponseJoin(
|
||||||
|
w, nil, fmt.Errorf("error create join request. %w", err),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.log.Debug("join request", slog.String("mnemonic", request.Mnemonic))
|
c.log.Debug("join request", slog.String("mnemonic", request.Mnemonic))
|
||||||
|
|
||||||
if !bip32.IsMnemonicValid(request.Mnemonic) {
|
if !bip32.IsMnemonicValid(request.Mnemonic) {
|
||||||
return fmt.Errorf("error invalid mnemonic. %w", ErrorAuthInvalidMnemonic)
|
return c.presenter.ResponseJoin(
|
||||||
|
w, nil, fmt.Errorf("error invalid mnemonic. %w", ErrorAuthInvalidMnemonic),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if _, err = c.usersInteractor.Create(ctx, users.CreateParams{
|
user, err := c.usersInteractor.Create(ctx, users.CreateParams{
|
||||||
Mnemonic: request.Mnemonic,
|
Mnemonic: request.Mnemonic,
|
||||||
IsAdmin: true,
|
IsAdmin: true,
|
||||||
Activate: true,
|
Activate: true,
|
||||||
}); err != nil {
|
})
|
||||||
return fmt.Errorf("error create new user. %w", err)
|
if err != nil {
|
||||||
|
return c.presenter.ResponseJoin(w, nil, fmt.Errorf("error create new user. %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return c.presenter.ResponseJoin(w, user, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *authController) JoinWithInvite(w http.ResponseWriter, req *http.Request) error {
|
func (c *authController) JoinWithInvite(w http.ResponseWriter, req *http.Request) error {
|
||||||
|
@ -9,6 +9,27 @@ type JoinRequest struct {
|
|||||||
Mnemonic string `json:"mnemonic"`
|
Mnemonic string `json:"mnemonic"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JoinResponse struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
Error *Error `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginRequest struct {
|
||||||
|
Mnemonc string `json:"mnemonic"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginResponse struct {
|
||||||
|
Ok bool `json:"ok"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
Error *Error `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
func BuildRequest[T any](data []byte) (*T, error) {
|
func BuildRequest[T any](data []byte) (*T, error) {
|
||||||
var req T
|
var req T
|
||||||
|
|
||||||
|
@ -5,19 +5,28 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/emochka2007/block-accounting/internal/interface/rest/domain"
|
"github.com/emochka2007/block-accounting/internal/interface/rest/domain"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||||
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthPresenter interface {
|
type AuthPresenter interface {
|
||||||
CreateJoinRequest(r *http.Request) (*domain.JoinRequest, error)
|
CreateJoinRequest(r *http.Request) (*domain.JoinRequest, error)
|
||||||
// ResponseJoin(w http.ResponseWriter, mnemonic string) error
|
ResponseJoin(w http.ResponseWriter, user *models.User, err error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type authPresenter struct{}
|
type authPresenter struct {
|
||||||
|
jwtInteractor jwt.JWTInteractor
|
||||||
|
}
|
||||||
|
|
||||||
func NewAuthPresenter() AuthPresenter {
|
func NewAuthPresenter(
|
||||||
return &authPresenter{}
|
jwtInteractor jwt.JWTInteractor,
|
||||||
|
) AuthPresenter {
|
||||||
|
return &authPresenter{
|
||||||
|
jwtInteractor: jwtInteractor,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *authPresenter) CreateJoinRequest(r *http.Request) (*domain.JoinRequest, error) {
|
func (p *authPresenter) CreateJoinRequest(r *http.Request) (*domain.JoinRequest, error) {
|
||||||
@ -37,17 +46,29 @@ func (p *authPresenter) CreateJoinRequest(r *http.Request) (*domain.JoinRequest,
|
|||||||
return &request, nil
|
return &request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (p *authPresenter) ResponseJoin(w http.ResponseWriter, mnemonic string) error {
|
func (p *authPresenter) ResponseJoin(w http.ResponseWriter, user *models.User, err error) error {
|
||||||
// out, err := json.Marshal(domain.JoinResponse{
|
resp := new(domain.JoinResponse)
|
||||||
// Mnemonic: mnemonic,
|
|
||||||
// })
|
|
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("error marshal join response. %w", err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if _, err = w.Write(out); err != nil {
|
if err != nil {
|
||||||
// return fmt.Errorf("error write response. %w", err)
|
// todo map error
|
||||||
// }
|
} else {
|
||||||
|
token, err := p.jwtInteractor.NewToken(user, 24*time.Hour)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error create access token. %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// return nil
|
resp.Ok = true
|
||||||
// }
|
resp.Token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error marshal join response. %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = w.Write(out); err != nil {
|
||||||
|
return fmt.Errorf("error write response. %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -12,6 +12,8 @@ type CommonConfig struct {
|
|||||||
LogLocal bool
|
LogLocal bool
|
||||||
LogFile string
|
LogFile string
|
||||||
LogAddSource bool
|
LogAddSource bool
|
||||||
|
|
||||||
|
JWTSecret []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type RestConfig struct {
|
type RestConfig struct {
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||||
"github.com/emochka2007/block-accounting/internal/usecase/repository/transactions"
|
"github.com/emochka2007/block-accounting/internal/usecase/repository/transactions"
|
||||||
"github.com/ethereum/go-ethereum"
|
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
@ -32,5 +31,7 @@ type smartContractInteractor struct {
|
|||||||
|
|
||||||
// todo
|
// todo
|
||||||
func (s *smartContractInteractor) SignTransaction(ctx context.Context, params SignTransactionParams) error {
|
func (s *smartContractInteractor) SignTransaction(ctx context.Context, params SignTransactionParams) error {
|
||||||
s.client.CallContract(ctx, ethereum.CallMsg{}, nil)
|
// s.client.CallContract(ctx, ethereum.CallMsg{}, nil)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||||
@ -21,7 +22,7 @@ type GetParams struct {
|
|||||||
type Repository interface {
|
type Repository interface {
|
||||||
Get(ctx context.Context, params GetParams) (*models.User, error)
|
Get(ctx context.Context, params GetParams) (*models.User, error)
|
||||||
Create(ctx context.Context, user *models.User) error
|
Create(ctx context.Context, user *models.User) error
|
||||||
Activate(ctx context.Context, id string) error
|
Activate(ctx context.Context, id uuid.UUID) error
|
||||||
Update(ctx context.Context, user *models.User) error
|
Update(ctx context.Context, user *models.User) error
|
||||||
Delete(ctx context.Context, id string) error
|
Delete(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
@ -89,8 +90,19 @@ func (r *repositorySQL) Create(ctx context.Context, user *models.User) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *repositorySQL) Activate(ctx context.Context, id string) error {
|
func (r *repositorySQL) Activate(ctx context.Context, id uuid.UUID) error {
|
||||||
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||||
|
query := sq.Update("users").
|
||||||
|
SetMap(sq.Eq{
|
||||||
|
"activated_at": time.Now(),
|
||||||
|
}).
|
||||||
|
Where(sq.Eq{
|
||||||
|
"id": id,
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||||
|
return fmt.Errorf("error mark user as activated in database. %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user