Skip to content

Commit

Permalink
feat!: add gRPC to serve gRPC api with create user and login user api
Browse files Browse the repository at this point in the history
  • Loading branch information
cukhoaimon committed Feb 6, 2024
1 parent cb7f7ca commit 2873bf8
Show file tree
Hide file tree
Showing 17 changed files with 297 additions and 104 deletions.
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ mock:
mockgen -package mockdb -destination db/mock/store.go github.com/cukhoaimon/SimpleBank/db/sqlc Store

proto:
rm -f pb/*.go # remove all previous files
protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \
--go-grpc_out=pb --go-grpc_opt=paths=source_relative \
proto/*.proto

tidy:
go mod tidy

.PHONY: postgres createdb dropdb migrate-up migrate-down sqlc test server mock dbdocs proto tidymake
.PHONY: postgres createdb dropdb migrate-up migrate-down sqlc test server mock dbdocs proto tidy
3 changes: 2 additions & 1 deletion app.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
DB_DRIVER=postgres
DB_SOURCE=postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable
SERVER_ADDRESS=0.0.0.0:8080
HTTP_SERVER_ADDRESS=0.0.0.0:8080
GRPC_SERVER_ADDRESS=0.0.0.0:50051
TOKEN_SYMMETRIC_KEY=12345678901234567890123456789012
TOKEN_DURATION=15m
REFRESH_TOKEN_DURATION=24h
17 changes: 17 additions & 0 deletions gapi/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gapi

import (
db "github.com/cukhoaimon/SimpleBank/db/sqlc"
"github.com/cukhoaimon/SimpleBank/pb"
"google.golang.org/protobuf/types/known/timestamppb"
)

func convertUser(user db.User) *pb.User {
return &pb.User{
Username: user.Username,
FullName: user.FullName,
Email: user.Email,
PasswordChangedAt: timestamppb.New(user.PasswordChangedAt),
CreatedAt: timestamppb.New(user.CreatedAt),
}
}
44 changes: 44 additions & 0 deletions gapi/rpc_create_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package gapi

import (
"context"
"errors"
db "github.com/cukhoaimon/SimpleBank/db/sqlc"
"github.com/cukhoaimon/SimpleBank/pb"
"github.com/cukhoaimon/SimpleBank/utils"
"github.com/lib/pq"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (server *Server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) {
hashedPassword, err := utils.HashPassword(req.GetPassword())
if err != nil {
return nil, status.Errorf(codes.Internal, "fail to hash password: %s", err)
}

arg := db.CreateUserParams{
Username: req.GetUsername(),
HashedPassword: hashedPassword,
FullName: req.GetFullName(),
Email: req.GetEmail(),
}

user, err := server.store.CreateUser(ctx, arg)
if err != nil {
var pqErr *pq.Error
if errors.As(err, &pqErr) {
switch pqErr.Code.Name() {
case "unique_violation":
return nil, status.Errorf(codes.AlreadyExists, "username already exists: %s", err)
}
}

return nil, status.Errorf(codes.Internal, "fail to create user: %s", err)
}

rsp := &pb.CreateUserResponse{
User: convertUser(user),
}
return rsp, nil
}
66 changes: 66 additions & 0 deletions gapi/rpc_login_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package gapi

import (
"context"
"database/sql"
"errors"
db "github.com/cukhoaimon/SimpleBank/db/sqlc"
"github.com/cukhoaimon/SimpleBank/pb"
"github.com/cukhoaimon/SimpleBank/utils"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
)

func (server *Server) LoginUser(ctx context.Context, req *pb.LoginUserRequest) (*pb.LoginUserResponse, error) {
user, err := server.store.GetUser(ctx, req.GetUsername())
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, status.Errorf(codes.NotFound, "user [%s] is not found in database", req.GetUsername())
}

return nil, status.Errorf(codes.Internal, "fail to get user [%s] from database", req.GetUsername())
}

err = utils.CheckPassword(req.Password, user.HashedPassword)
if err != nil {
return nil, status.Error(codes.Unauthenticated, "wrong password")

}

token, accessTokenPayload, err := server.tokenMaker.CreateToken(req.Username, server.config.TokenDuration)
if err != nil {
return nil, status.Error(codes.Internal, "fail to create access token")
}

refreshToken, refreshTokenPayload, err := server.tokenMaker.CreateToken(req.Username, server.config.RefreshTokenDuration)
if err != nil {
return nil, status.Error(codes.Internal, "fail to create refresh access token")
}

arg := db.CreateSessionParams{
ID: accessTokenPayload.Id,
Username: accessTokenPayload.Username,
RefreshToken: refreshToken,
UserAgent: "",
ClientIp: "",
IsBlocked: false,
ExpiresAt: refreshTokenPayload.ExpiredAt,
}

session, err := server.store.CreateSession(ctx, arg)
if err != nil {
return nil, status.Error(codes.Internal, "fail to create session")
}

res := &pb.LoginUserResponse{
SessionId: session.ID.String(),
AccessToken: token,
AccessTokenExpiresAt: timestamppb.New(accessTokenPayload.ExpiredAt),
RefreshToken: refreshToken,
RefreshTokenExpiresAt: timestamppb.New(refreshTokenPayload.ExpiredAt),
User: convertUser(user),
}

return res, nil
}
32 changes: 32 additions & 0 deletions gapi/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gapi

import (
db "github.com/cukhoaimon/SimpleBank/db/sqlc"
"github.com/cukhoaimon/SimpleBank/pb"
"github.com/cukhoaimon/SimpleBank/token"
"github.com/cukhoaimon/SimpleBank/utils"
)

// Server serves gRPC request
type Server struct {
pb.UnimplementedSimpleBankServer
config utils.Config
tokenMaker token.Maker
store db.Store
}

// NewServer will return new gRPC server
func NewServer(store db.Store, config utils.Config) (*Server, error) {
maker, err := token.NewPasetoMaker(config.TokenSymmetricKey)
if err != nil {
return nil, err
}

server := &Server{
store: store,
tokenMaker: maker,
config: config,
}

return server, nil
}
33 changes: 32 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ package main

import (
"database/sql"
"github.com/cukhoaimon/SimpleBank/gapi"
"github.com/cukhoaimon/SimpleBank/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"log"
"net"

"github.com/cukhoaimon/SimpleBank/api"
db "github.com/cukhoaimon/SimpleBank/db/sqlc"
Expand All @@ -24,12 +29,38 @@ func main() {
}

store := db.NewStore(conn)
runGRPCServer(store, config)
}

func runGinServer(store db.Store, config utils.Config) {
server, err := api.NewServer(store, config)
if err != nil {
log.Fatal("Cannot create server")
}

if err = server.Start(config.ServerAddress); err != nil {
if err = server.Start(config.HttpServerAddress); err != nil {
log.Fatal("Cannot start server")
}
}

func runGRPCServer(store db.Store, config utils.Config) {
server, err := gapi.NewServer(store, config)
if err != nil {
log.Fatal("Cannot create gRPC server")
}

gRPCServer := grpc.NewServer()
pb.RegisterSimpleBankServer(gRPCServer, server)
// allow client to know what RPCs currently available in server
reflection.Register(gRPCServer)

listener, err := net.Listen("tcp", config.GrpcServerAddress)
if err != nil {
log.Fatal("Cannot create tcp-listener for gRPC server")
}

log.Printf("start gRPC server at: %s", listener.Addr().String())
if err = gRPCServer.Serve(listener); err != nil {
log.Fatal("Cannot serve gRPC server")
}
}
12 changes: 6 additions & 6 deletions pb/rpc_create_user.pb.go

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

Loading

0 comments on commit 2873bf8

Please sign in to comment.