Skip to content

Commit

Permalink
Merge pull request #3 from Chuiko-GIT/add-migrations-and-config
Browse files Browse the repository at this point in the history
Add database migrations and configuration files
  • Loading branch information
Chuiko-GIT authored Aug 25, 2024
2 parents 4e84af7 + c378ba1 commit 86ba548
Show file tree
Hide file tree
Showing 16 changed files with 587 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ go.work.sum

# env file
.env
prod.env
local.env

/bin/
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
include .env
LOCAL_BIN:=$(CURDIR)/bin

install-deps:
GOBIN=$(LOCAL_BIN) go install google.golang.org/protobuf/cmd/[email protected]
GOBIN=$(LOCAL_BIN) go install -mod=mod google.golang.org/grpc/cmd/[email protected]
GOBIN=$(LOCAL_BIN) go install github.com/pressly/goose/v3/cmd/[email protected]

get-deps:
go get -u google.golang.org/protobuf/cmd/protoc-gen-go
go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc

local-migration-status:
${LOCAL_BIN}/goose -dir ${LOCAL_MIGRATION_DIR} postgres ${LOCAL_MIGRATION_DSN} status -v

local-migration-up:
${LOCAL_BIN}/goose -dir ${LOCAL_MIGRATION_DIR} postgres ${LOCAL_MIGRATION_DSN} up -v

local-migration-down:
${LOCAL_BIN}/goose -dir ${LOCAL_MIGRATION_DIR} postgres ${LOCAL_MIGRATION_DSN} down -v

generate:
make generate-user-api

Expand Down
63 changes: 63 additions & 0 deletions cmd/grpc_client/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"context"
"log"
"time"

"github.com/fatih/color"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/Chuiko-GIT/auth/pkg/user_api"
)

const (
address = "localhost:50051"
userID = 1
)

func main() {
conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("failed to connect to server: %v", err)
}
defer func() {
if err = conn.Close(); err != nil {
log.Println(err)
}
}()

c := user_api.NewUserAPIClient(conn)

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

getUser, err := c.Get(ctx, &user_api.GetRequest{Id: userID})
if err != nil {
log.Fatalf("failed to get user by id: %v", err)
}

log.Printf(color.RedString("User get:\n"), color.GreenString("%+v", getUser.GetUser()))

createUser, err := c.Create(ctx, &user_api.CreateRequest{})
if err != nil {
log.Fatalf("failed to create user: %v", err)
}

log.Printf(color.RedString("User create:\n"), color.GreenString("%+v", createUser.GetId()))

updateUser, err := c.Update(ctx, &user_api.UpdateRequest{})
if err != nil {
log.Fatalf("failed to update user: %v", err)
}

log.Printf(color.RedString("User update:\n"), color.GreenString("%+v", updateUser.String()))

deleteUser, err := c.Delete(ctx, &user_api.DeleteRequest{})
if err != nil {
log.Fatalf("failed to delete user: %v", err)
}

log.Printf(color.RedString("User delete:\n"), color.GreenString("%+v", deleteUser.String()))
}
127 changes: 104 additions & 23 deletions cmd/grpc_server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,56 @@ package main

import (
"context"
"fmt"
"flag"
"log"
"net"
"time"

"github.com/brianvoe/gofakeit"
sq "github.com/Masterminds/squirrel"
"github.com/jackc/pgx/v4/pgxpool"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/Chuiko-GIT/chat/pkg/user_api"
"github.com/Chuiko-GIT/auth/internal/config"
"github.com/Chuiko-GIT/auth/internal/config/env"
"github.com/Chuiko-GIT/auth/pkg/user_api"
)

const (
grpcPort = 50051
var (
configPath string
)

func init() {
flag.StringVar(&configPath, "config-path", ".env", "path to config file")
}

type server struct {
user_api.UnimplementedUserAPIServer
pool *pgxpool.Pool
}

func (s server) Create(ctx context.Context, req *user_api.CreateRequest) (*user_api.CreateResponse, error) {
builderInsert := sq.Insert("users").
PlaceholderFormat(sq.Dollar).
Columns("name", "email", "password", "password_confirm", "role").
Values(req.User.Name, req.User.Email, req.User.Password, req.User.PasswordConfirm, req.User.Role.String()).
Suffix("RETURNING id")

query, args, err := builderInsert.ToSql()
if err != nil {
log.Fatalf("failed to build query: %v", err)
}

var userID int
if err = s.pool.QueryRow(ctx, query, args...).Scan(&userID); err != nil {
log.Fatalf("failed to select users: %v", err)
}

log.Printf("inserted user with id: %d", userID)

return &user_api.CreateResponse{
Id: gofakeit.Int64(),
Id: int64(userID),
}, nil
}

Expand All @@ -34,36 +60,91 @@ func (s server) Delete(ctx context.Context, req *user_api.DeleteRequest) (*empty
}

func (s server) Update(ctx context.Context, req *user_api.UpdateRequest) (*emptypb.Empty, error) {
builderUpdate := sq.Update("users").
PlaceholderFormat(sq.Dollar).
Set("name", "Alex").
Set("email", "[email protected]").
Set("password", "test-test").
Set("password_confirm", "true").
Set("role", "admin").
Set("updated_at", time.Now()).
Where(sq.Eq{"id": req.GetId()})

query, args, err := builderUpdate.ToSql()
if err != nil {
log.Fatalf("failed to build query: %v", err)
}

res, err := s.pool.Exec(ctx, query, args...)
if err != nil {
log.Fatalf("failed to update user: %v", err)
}

log.Printf("updated %d rows", res.RowsAffected())

return &emptypb.Empty{}, nil
}

func (s server) Get(ctx context.Context, req *user_api.GetRequest) (*user_api.GetResponse, error) {
return &user_api.GetResponse{
User: &user_api.User{
Id: req.GetId(),
User: &user_api.UserInfo{
Name: "TEST ROMA",
Email: "TEST EMAIL",
Password: gofakeit.Password(true, true, true, true, true, 1),
PasswordConfirm: gofakeit.BeerName(),
Role: user_api.Role_USER,
},
CreatedAt: timestamppb.New(gofakeit.Date()),
UpdatedAt: timestamppb.New(gofakeit.Date()),
},
}, nil
builderSelectOne := sq.Select("id", "name", "email", "password", "password_confirm", "role", "created_at", "updated_at").
From("users").
PlaceholderFormat(sq.Dollar).
Where(sq.Eq{"id": req.GetId()}).
Limit(1)

query, args, err := builderSelectOne.ToSql()
if err != nil {
log.Fatalf("failed to build query: %v", err)
}

var resp user_api.User
err = s.pool.
QueryRow(ctx, query, args...).
Scan(resp.Id, resp.User.Name, resp.User.Email, resp.User.Password, resp.User.PasswordConfirm, resp.User.Role, resp.CreatedAt, resp.UpdatedAt)
if err != nil {
log.Fatalf("failed to select user: %v", err)
}

log.Printf("id: %d, name: %s, email: %s,password: %s,passwordConfirm: %s,role: %s, created_at: %v, updated_at: %v\n",
resp.Id, resp.User.Name, resp.User.Email, resp.User.Password, resp.User.PasswordConfirm, resp.User.Role, resp.CreatedAt, resp.UpdatedAt)

return &user_api.GetResponse{User: &resp}, nil

}

func main() {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort))
flag.Parse()
ctx := context.Background()

if err := config.Load(configPath); err != nil {
log.Fatalf("failed to load config: %v", err)
}

pgConfig, err := env.NewPGConfig()
if err != nil {
log.Fatalf("failed to get pg config: %v", err)
}

pool, err := pgxpool.Connect(ctx, pgConfig.DSN())
if err != nil {
log.Fatalf("failed to connect to database: %v", err)
}

defer pool.Close()

grpcConfig, err := env.NewGRPCConfig()
if err != nil {
log.Fatalf("failed to get grpc config: %v", err)
}

lis, err := net.Listen("tcp", grpcConfig.Address())
if err != nil {
log.Fatalf("failed to listen: %v", err)
}

s := grpc.NewServer()
reflection.Register(s)
user_api.RegisterUserAPIServer(s, server{})
user_api.RegisterUserAPIServer(s, server{pool: pool})

log.Printf("server listening at %v", lis.Addr())

Expand Down
40 changes: 40 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
version: '3'

volumes:
postgres_volume_local:
postgres_volume_prod:

services:
pg-local:
image: postgres:14-alpine3.17
env_file:
- local.env
ports:
- "54321:5432"
volumes:
- postgres_volume_local:/var/lib/postgresql/data

pg-prod:
image: postgres:14-alpine3.17
env_file:
- prod.env
ports:
- "54322:5432"
volumes:
- postgres_volume_prod:/var/lib/postgresql/data

migrator-local:
build:
context: .
dockerfile: migration_local.Dockerfile
restart: on-failure
environment:
DB_HOST: pg-local

migrator-prod:
build:
context: .
dockerfile: migration_prod.Dockerfile
restart: on-failure
environment:
DB_HOST: pg-prod
16 changes: 15 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
module github.com/Chuiko-GIT/chat
module github.com/Chuiko-GIT/auth

go 1.21

toolchain go1.22.5

require (
github.com/Masterminds/squirrel v1.5.4
github.com/brianvoe/gofakeit v3.18.0+incompatible
github.com/fatih/color v1.17.0
github.com/jackc/pgx/v4 v4.18.3
github.com/joho/godotenv v1.5.1
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2
)

require (
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.3 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
Expand Down
Loading

0 comments on commit 86ba548

Please sign in to comment.