add add user method

This commit is contained in:
2026-06-29 02:11:28 +07:00
parent 0f9bf8dfc1
commit 18fad25b27
5 changed files with 113 additions and 9 deletions
+14 -4
View File
@@ -3,13 +3,15 @@ package main
import ( import (
"context" "context"
_ "embed" _ "embed"
"evening_detective_server/internal/app"
"evening_detective_server/internal/repos/users_repo"
"evening_detective_server/internal/services/users_service"
proto "evening_detective_server/proto"
"log" "log"
"net" "net"
"net/http" "net/http"
"os" "os"
"evening_detective_server/internal/app"
proto "evening_detective_server/proto"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
"github.com/joho/godotenv" "github.com/joho/godotenv"
@@ -38,6 +40,9 @@ func main() {
log.Fatalf("QueryRow failed: %v\n", err) log.Fatalf("QueryRow failed: %v\n", err)
} }
usersRepo := users_repo.NewUserRepo(dbpool)
usersService := users_service.NewUsersService(usersRepo)
// Create a listener on TCP port // Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080") lis, err := net.Listen("tcp", ":8080")
if err != nil { if err != nil {
@@ -47,7 +52,12 @@ func main() {
// Create a gRPC server object // Create a gRPC server object
s := grpc.NewServer() s := grpc.NewServer()
// Attach the Greeter service to the server // Attach the Greeter service to the server
proto.RegisterEveningDetectiveServerServer(s, app.NewServer()) proto.RegisterEveningDetectiveServerServer(
s,
app.NewServer(
usersService,
),
)
// Serve gRPC server // Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080") log.Println("Serving gRPC on 0.0.0.0:8080")
go func() { go func() {
+17 -4
View File
@@ -2,15 +2,22 @@ package app
import ( import (
"context" "context"
"evening_detective_server/internal/services/users_service"
proto "evening_detective_server/proto" proto "evening_detective_server/proto"
) )
type server struct { type server struct {
proto.UnsafeEveningDetectiveServerServer proto.UnsafeEveningDetectiveServerServer
usersService *users_service.UsersService
} }
func NewServer() proto.EveningDetectiveServerServer { func NewServer(
return &server{} usersService *users_service.UsersService,
) proto.EveningDetectiveServerServer {
return &server{
usersService: usersService,
}
} }
func (s *server) Ping(_ context.Context, _ *proto.PingReq) (*proto.PingRsp, error) { func (s *server) Ping(_ context.Context, _ *proto.PingReq) (*proto.PingRsp, error) {
@@ -21,6 +28,12 @@ func (s *server) Echo(_ context.Context, req *proto.EchoReq) (*proto.EchoRsp, er
return &proto.EchoRsp{Text: req.Text}, nil return &proto.EchoRsp{Text: req.Text}, nil
} }
func (s *server) Signup(context.Context, *proto.SignupReq) (*proto.SignupRsp, error) { func (s *server) Signup(ctx context.Context, signupReq *proto.SignupReq) (*proto.SignupRsp, error) {
panic("unimplemented") err := s.usersService.AddUser(ctx, signupReq.Username, signupReq.Email)
if err != nil {
return &proto.SignupRsp{
Error: err.Error(),
}, nil
}
return &proto.SignupRsp{}, nil
} }
+50
View File
@@ -0,0 +1,50 @@
package users_repo
import (
"context"
"errors"
"github.com/jackc/pgx/v5/pgxpool"
)
type UsersRepo struct {
pool *pgxpool.Pool
}
func NewUserRepo(pool *pgxpool.Pool) *UsersRepo {
return &UsersRepo{
pool: pool,
}
}
func (s *UsersRepo) AddUser(
ctx context.Context,
username string,
email string,
passwoedHash string,
role string,
) error {
tag, err := s.pool.Exec(
ctx,
`INSERT INTO users (username, email, password_hash, role)
SELECT $1, $2, $3, $4
WHERE NOT EXISTS (
SELECT 1 FROM users
WHERE username = $5 OR email = $6
)`,
username,
email,
passwoedHash,
role,
username,
email,
)
if err != nil {
return err
}
if tag.RowsAffected() == 0 {
return errors.New("username или email уже используется")
}
return nil
}
@@ -0,0 +1,31 @@
package users_service
import (
"context"
"evening_detective_server/internal/repos/users_repo"
)
type UsersService struct {
usersRepo *users_repo.UsersRepo
}
func NewUsersService(usersRepo *users_repo.UsersRepo) *UsersService {
return &UsersService{
usersRepo: usersRepo,
}
}
func (s *UsersService) AddUser(
ctx context.Context,
username string,
email string,
) error {
err := s.usersRepo.AddUser(
ctx,
username,
email,
"hello", // TODO: generate password and send email
"user",
)
return err
}
@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS users (
username VARCHAR(50) NOT NULL UNIQUE, username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL, password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'user' CHECK (role IN ('admin', 'author', 'organizer', 'user')), role VARCHAR(20) CHECK (role IN ('admin', 'author', 'organizer', 'user')),
is_active BOOLEAN DEFAULT TRUE, is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );