2024-05-24 17:44:24 +00:00
|
|
|
package users
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
|
|
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
|
|
|
sqltools "github.com/emochka2007/block-accounting/internal/pkg/sqlutils"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
|
|
|
type GetParams struct {
|
|
|
|
Ids uuid.UUIDs
|
2024-05-26 10:42:06 +00:00
|
|
|
PKs [][]byte
|
2024-05-24 17:44:24 +00:00
|
|
|
OrganizationId uuid.UUID
|
|
|
|
Seed []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo implement
|
|
|
|
type Repository interface {
|
|
|
|
Get(ctx context.Context, params GetParams) ([]*models.User, error)
|
|
|
|
Create(ctx context.Context, user *models.User) error
|
|
|
|
Activate(ctx context.Context, id uuid.UUID) error
|
|
|
|
Update(ctx context.Context, user *models.User) error
|
|
|
|
Delete(ctx context.Context, id string) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type repositorySQL struct {
|
|
|
|
db *sql.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRepository(db *sql.DB) Repository {
|
|
|
|
return &repositorySQL{
|
|
|
|
db: db,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *repositorySQL) Conn(ctx context.Context) sqltools.DBTX {
|
|
|
|
if tx, ok := ctx.Value(sqltools.TxCtxKey).(*sql.Tx); ok {
|
|
|
|
return tx
|
|
|
|
}
|
|
|
|
|
|
|
|
return s.db
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]*models.User, error) {
|
|
|
|
var users []*models.User = make([]*models.User, 0, len(params.Ids))
|
|
|
|
|
|
|
|
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) {
|
2024-05-24 23:39:32 +00:00
|
|
|
query := sq.Select("u.id, u.name, u.email, u.phone, u.tg, u.seed, u.created_at, u.activated_at, u.public_key, u.mnemonic").
|
2024-05-24 17:44:24 +00:00
|
|
|
From("users as u").
|
|
|
|
PlaceholderFormat(sq.Dollar)
|
|
|
|
|
|
|
|
if len(params.Ids) > 0 {
|
|
|
|
query = query.Where(sq.Eq{
|
|
|
|
"u.id": params.Ids,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-05-26 10:42:06 +00:00
|
|
|
if len(params.PKs) > 0 {
|
|
|
|
query = query.Where(sq.Eq{
|
|
|
|
"u.public_key": params.PKs,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-05-24 17:44:24 +00:00
|
|
|
if params.OrganizationId != uuid.Nil {
|
|
|
|
query = query.InnerJoin(
|
|
|
|
"organizations_users as ou on ou.user_id = u.id",
|
|
|
|
).Where(sq.Eq{
|
|
|
|
"ou.organization_id": params.OrganizationId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if params.Seed != nil {
|
|
|
|
query = query.Where("u.seed = ?", params.Seed)
|
|
|
|
}
|
|
|
|
|
2024-05-26 10:42:06 +00:00
|
|
|
if params.PKs != nil {
|
|
|
|
fmt.Println(query.ToSql())
|
|
|
|
}
|
|
|
|
|
2024-05-24 17:44:24 +00:00
|
|
|
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error fetch data from database. %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if cErr := rows.Close(); cErr != nil {
|
|
|
|
err = errors.Join(fmt.Errorf("error close database rows. %w", cErr), err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var (
|
|
|
|
id uuid.UUID
|
|
|
|
|
|
|
|
name string
|
|
|
|
email string
|
|
|
|
phone string
|
|
|
|
tg string
|
|
|
|
|
|
|
|
seed []byte
|
2024-05-24 22:45:56 +00:00
|
|
|
pk []byte
|
2024-05-24 17:44:24 +00:00
|
|
|
//isAdmin bool
|
|
|
|
createdAt time.Time
|
|
|
|
activatedAt sql.NullTime
|
2024-05-24 23:39:32 +00:00
|
|
|
mnemonic string
|
2024-05-24 17:44:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if err = rows.Scan(
|
|
|
|
&id,
|
|
|
|
&name,
|
|
|
|
&email,
|
|
|
|
&phone,
|
|
|
|
&tg,
|
|
|
|
&seed,
|
|
|
|
&createdAt,
|
|
|
|
&activatedAt,
|
2024-05-24 22:45:56 +00:00
|
|
|
&pk,
|
2024-05-24 23:39:32 +00:00
|
|
|
&mnemonic,
|
2024-05-24 17:44:24 +00:00
|
|
|
); err != nil {
|
|
|
|
return fmt.Errorf("error scan row. %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
users = append(users, &models.User{
|
|
|
|
ID: id,
|
|
|
|
Name: name,
|
|
|
|
Credentails: &models.UserCredentials{
|
|
|
|
Email: email,
|
|
|
|
Phone: phone,
|
|
|
|
Telegram: tg,
|
|
|
|
},
|
|
|
|
Bip39Seed: seed,
|
2024-05-24 22:45:56 +00:00
|
|
|
PK: pk,
|
2024-05-24 23:39:32 +00:00
|
|
|
Mnemonic: mnemonic,
|
2024-05-24 17:44:24 +00:00
|
|
|
//Admin: isAdmin,
|
|
|
|
CreatedAt: createdAt,
|
|
|
|
Activated: activatedAt.Valid,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return users, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *repositorySQL) Create(ctx context.Context, user *models.User) error {
|
|
|
|
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
2024-05-24 23:39:32 +00:00
|
|
|
columns := []string{"id", "name", "email", "phone", "tg", "seed", "public_key", "mnemonic", "created_at"}
|
2024-05-24 17:44:24 +00:00
|
|
|
|
|
|
|
values := []any{
|
|
|
|
user.ID,
|
|
|
|
user.Name,
|
|
|
|
user.Credentails.Email,
|
|
|
|
user.Credentails.Phone,
|
|
|
|
user.Credentails.Telegram,
|
|
|
|
user.Bip39Seed,
|
2024-05-24 22:45:56 +00:00
|
|
|
user.PK,
|
2024-05-24 23:39:32 +00:00
|
|
|
user.Mnemonic,
|
2024-05-24 17:44:24 +00:00
|
|
|
user.CreatedAt,
|
|
|
|
}
|
|
|
|
|
|
|
|
if user.Activated {
|
|
|
|
columns = append(columns, "activated_at")
|
|
|
|
values = append(values, user.CreatedAt)
|
|
|
|
}
|
|
|
|
|
|
|
|
query := sq.Insert("users").Columns(
|
|
|
|
columns...,
|
|
|
|
).Values(
|
|
|
|
values...,
|
|
|
|
).PlaceholderFormat(sq.Dollar)
|
|
|
|
|
|
|
|
if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
|
|
|
return fmt.Errorf("error insert new user. %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *repositorySQL) Activate(ctx context.Context, id uuid.UUID) 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
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *repositorySQL) Update(ctx context.Context, user *models.User) error {
|
|
|
|
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *repositorySQL) Delete(ctx context.Context, id string) error {
|
|
|
|
if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|