Skip to content

Commit

Permalink
Merge pull request #7 from isd-sgcu/gear-be/fdr-50-be-gateway-checkin
Browse files Browse the repository at this point in the history
Gear be/fdr 50 be gateway checkin
  • Loading branch information
macgeargear authored Jun 29, 2024
2 parents c131f38 + 92ac6c9 commit f69c8a8
Show file tree
Hide file tree
Showing 15 changed files with 952 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ mock-gen:
mockgen -source ./internal/pin/pin.service.go -destination ./mocks/pin/pin.service.go
mockgen -source ./internal/selection/selection.service.go -destination ./mocks/selection/selection.service.go
mockgen -source ./internal/selection/selection.client.go -destination ./mocks/selection/selection.client.go
mockgen -source ./internal/checkin/checkin.service.go -destination ./mocks/checkin/checkin.service.go
mockgen -source ./internal/checkin/checkin.client.go -destination ./mocks/checkin/checkin.client.go
mockgen -source ./internal/router/context.go -destination ./mocks/router/context.mock.go
mockgen -source ./internal/validator/validator.go -destination ./mocks/validator/validator.mock.go

Expand Down
15 changes: 15 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (

"github.com/isd-sgcu/rpkm67-gateway/config"
auth "github.com/isd-sgcu/rpkm67-gateway/internal/auth"
"github.com/isd-sgcu/rpkm67-gateway/internal/checkin"
"github.com/isd-sgcu/rpkm67-gateway/internal/router"
"github.com/isd-sgcu/rpkm67-gateway/internal/validator"
"github.com/isd-sgcu/rpkm67-gateway/logger"
"github.com/isd-sgcu/rpkm67-gateway/middleware"
authProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/auth/auth/v1"
checkinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/checkin/checkin/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
Expand All @@ -34,16 +36,29 @@ func main() {
logger.Sugar().Fatalf("cannot connect to auth service", err)
}

checkinConn, err := grpc.NewClient(conf.Svc.CheckIn, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
logger.Sugar().Fatalf("cannot connect to checkin service", err)
}

authClient := authProto.NewAuthServiceClient(authConn)
authSvc := auth.NewService(authClient, logger)
authHdr := auth.NewHandler(authSvc, validate, logger)

checkinClient := checkinProto.NewCheckInServiceClient(checkinConn)
checkinSvc := checkin.NewService(checkinClient, logger)
checkinHdr := checkin.NewHandler(checkinSvc, validate, logger)

r := router.New(conf, corsHandler, authMiddleware)

r.V1Get("/auth/google-url", authHdr.GetGoogleLoginUrl)
r.V1Post("/auth/verify-google", authHdr.VerifyGoogleLogin)
r.V1Post("/auth/test", authHdr.Test)

r.V1Post("/checkin/create", checkinHdr.Create)
r.V1Get("/checkin/:userId", checkinHdr.FindByUserID)
r.V1Get("/checkin/email/:email", checkinHdr.FindByEmail)

if err := r.Run(fmt.Sprintf(":%v", conf.App.Port)); err != nil {
logger.Fatal("unable to start server")
}
Expand Down
6 changes: 4 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ type AppConfig struct {
}

type ServiceConfig struct {
Auth string
Auth string
CheckIn string
}

type CorsConfig struct {
Expand All @@ -39,7 +40,8 @@ func LoadConfig() (*Config, error) {
}

serviceConfig := ServiceConfig{
Auth: os.Getenv("SERVICE_AUTH"),
Auth: os.Getenv("SERVICE_AUTH"),
CheckIn: os.Getenv("SERVICE_CHECKIN"),
}

corsConfig := CorsConfig{
Expand Down
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ require (
google.golang.org/grpc v1.64.0
)

require github.com/stretchr/objx v0.5.2 // indirect

require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
Expand Down
15 changes: 0 additions & 15 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/isd-sgcu/rpkm67-go-proto v0.0.4 h1:ZO1m0EfTtjQ2IcRy6mUHj+mAb4loM3ckeisKefKqKmY=
github.com/isd-sgcu/rpkm67-go-proto v0.0.4/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.0.5 h1:8zTvNQ0NPokoVRK/NQJYxWjcBFMZNK0avotPs9RSPh0=
github.com/isd-sgcu/rpkm67-go-proto v0.0.5/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.0.6 h1:alECc0pLyJmbJ2cLBukNDplka+ucWutR6yLXqAn0lJM=
github.com/isd-sgcu/rpkm67-go-proto v0.0.6/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.0.7 h1:BrHjp7hDFmXTMuMKuA4mK3bjtHTvzozO0vYC1hV1a+w=
github.com/isd-sgcu/rpkm67-go-proto v0.0.7/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.1.2 h1:sLq8HWYaqnv0VO7cD5o4pLu+Mzf2fnIJuAT7DGqRaB8=
github.com/isd-sgcu/rpkm67-go-proto v0.1.2/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.1.3 h1:9+wrvKUUY5GDot1SmU9HtUgf8JzhPLHWKtCfmBQU+Yw=
github.com/isd-sgcu/rpkm67-go-proto v0.1.3/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.1.5 h1:WShrm8DeVqIY1ZelgM88vW8LMnLxF6dTt650A0YkC8U=
github.com/isd-sgcu/rpkm67-go-proto v0.1.5/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/isd-sgcu/rpkm67-go-proto v0.1.6 h1:6mubghe7HuGJYv+hgpIxJBBrmVk5UdjHjdvzykLLhQ0=
github.com/isd-sgcu/rpkm67-go-proto v0.1.6/go.mod h1:Z5SYz5kEe4W+MdqPouF0zEOiaqvg+s9I1S5d0q6e+Jw=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
Expand Down Expand Up @@ -111,7 +97,6 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down
36 changes: 36 additions & 0 deletions internal/checkin/checkin.client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package checkin

import (
"context"

checkinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/checkin/checkin/v1"
"google.golang.org/grpc"
)

type clientImpl struct {
client checkinProto.CheckInServiceClient
}

type Client interface {
Create(ctx context.Context, in *checkinProto.CreateCheckInRequest, opts ...grpc.CallOption) (*checkinProto.CreateCheckInResponse, error)
FindByUserId(ctx context.Context, in *checkinProto.FindByUserIdCheckInRequest, opts ...grpc.CallOption) (*checkinProto.FindByUserIdCheckInResponse, error)
FindByEmail(ctx context.Context, in *checkinProto.FindByEmailCheckInRequest, opts ...grpc.CallOption) (*checkinProto.FindByEmailCheckInResponse, error)
}

func NewClient(client checkinProto.CheckInServiceClient) Client {
return &clientImpl{
client: client,
}
}

func (c *clientImpl) Create(ctx context.Context, in *checkinProto.CreateCheckInRequest, opts ...grpc.CallOption) (*checkinProto.CreateCheckInResponse, error) {
return c.client.Create(ctx, in, opts...)
}

func (c *clientImpl) FindByUserId(ctx context.Context, in *checkinProto.FindByUserIdCheckInRequest, opts ...grpc.CallOption) (*checkinProto.FindByUserIdCheckInResponse, error) {
return c.client.FindByUserId(ctx, in, opts...)
}

func (c *clientImpl) FindByEmail(ctx context.Context, in *checkinProto.FindByEmailCheckInRequest, opts ...grpc.CallOption) (*checkinProto.FindByEmailCheckInResponse, error) {
return c.client.FindByEmail(ctx, in, opts...)
}
116 changes: 116 additions & 0 deletions internal/checkin/checkin.handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package checkin

import (
"net/http"
"strings"

"github.com/isd-sgcu/rpkm67-gateway/internal/dto"
"github.com/isd-sgcu/rpkm67-gateway/internal/router"
"github.com/isd-sgcu/rpkm67-gateway/internal/validator"
"go.uber.org/zap"
)

type Handler interface {
Create(c router.Context)
FindByEmail(c router.Context)
FindByUserID(c router.Context)
}

func NewHandler(svc Service, validate validator.DtoValidator, log *zap.Logger) Handler {
return &handlerImpl{
svc: svc,
validate: validate,
log: log,
}
}

type handlerImpl struct {
svc Service
validate validator.DtoValidator
log *zap.Logger
}

func (h *handlerImpl) Create(c router.Context) {
body := &dto.CreateCheckInRequest{}
if err := c.Bind(body); err != nil {
h.log.Named("Create").Error("Bind: failed to bind request body", zap.Error(err))
c.BadRequestError(err.Error())
return
}

if errorList := h.validate.Validate(body); errorList != nil {
h.log.Named("Create").Error("Validate: ", zap.Strings("errorList", errorList))
c.BadRequestError(strings.Join(errorList, ", "))
return
}

req := &dto.CreateCheckInRequest{
Email: body.Email,
UserID: body.UserID,
Event: body.Event,
}

res, appErr := h.svc.Create(req)
if appErr != nil {
h.log.Named("Create").Error("Create: ", zap.Error(appErr))
c.ResponseError(appErr)
return
}

c.JSON(http.StatusCreated, &dto.CreateCheckInResponse{
CheckIn: &dto.CheckIn{
ID: res.CheckIn.ID,
UserID: res.CheckIn.UserID,
Email: res.CheckIn.Email,
Event: res.CheckIn.Event,
},
})
}

func (h *handlerImpl) FindByEmail(c router.Context) {
email := c.Param("email")
if email == "" {
h.log.Named("FindByEmail").Error("FindByEmail: email should not be empty")
c.BadRequestError("email should not be empty")
return
}

req := &dto.FindByEmailCheckInRequest{
Email: email,
}

res, appErr := h.svc.FindByEmail(req)
if appErr != nil {
h.log.Named("FindByEmail").Error("FindByEmail: ", zap.Error(appErr))
c.ResponseError(appErr)
return
}

c.JSON(http.StatusOK, &dto.FindByEmailCheckInResponse{
CheckIns: res.CheckIns,
})
}

func (h *handlerImpl) FindByUserID(c router.Context) {
userId := c.Param("userId")
if userId == "" {
h.log.Named("FindByUserID").Error("FindByUserID: user_id should not be empty")
c.BadRequestError("user_id should not be empty")
return
}

req := &dto.FindByUserIdCheckInRequest{
UserID: userId,
}

res, appErr := h.svc.FindByUserID(req)
if appErr != nil {
h.log.Named("FindByUserID").Error("FindByUserID: ", zap.Error(appErr))
c.ResponseError(appErr)
return
}

c.JSON(http.StatusOK, &dto.FindByUserIdCheckInResponse{
CheckIns: res.CheckIns,
})
}
122 changes: 122 additions & 0 deletions internal/checkin/checkin.service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package checkin

import (
"context"
"time"

"github.com/isd-sgcu/rpkm67-gateway/apperror"
"github.com/isd-sgcu/rpkm67-gateway/internal/dto"
checkinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/checkin/checkin/v1"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

type Service interface {
Create(req *dto.CreateCheckInRequest) (*dto.CreateCheckInResponse, *apperror.AppError)
FindByUserID(req *dto.FindByUserIdCheckInRequest) (*dto.FindByUserIdCheckInResponse, *apperror.AppError)
FindByEmail(req *dto.FindByEmailCheckInRequest) (*dto.FindByEmailCheckInResponse, *apperror.AppError)
}

type serviceImpl struct {
client checkinProto.CheckInServiceClient
log *zap.Logger
}

func NewService(client checkinProto.CheckInServiceClient, log *zap.Logger) Service {
return &serviceImpl{
client: client,
log: log,
}
}

func (s *serviceImpl) Create(req *dto.CreateCheckInRequest) (*dto.CreateCheckInResponse, *apperror.AppError) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

res, err := s.client.Create(ctx, &checkinProto.CreateCheckInRequest{
Email: req.Email,
UserId: req.UserID,
Event: req.Event,
})
if err != nil {
s.log.Named("Create").Error("Create: ", zap.Error(err))
st, ok := status.FromError(err)
if !ok {
return nil, apperror.InternalServer
}
switch st.Code() {
case codes.InvalidArgument:
return nil, apperror.BadRequest
case codes.Internal:
return nil, apperror.InternalServer
default:
return nil, apperror.ServiceUnavailable
}
}

return &dto.CreateCheckInResponse{
CheckIn: &dto.CheckIn{
ID: res.CheckIn.Id,
UserID: res.CheckIn.UserId,
Email: res.CheckIn.Email,
Event: res.CheckIn.Event,
},
}, nil
}

func (s *serviceImpl) FindByEmail(req *dto.FindByEmailCheckInRequest) (*dto.FindByEmailCheckInResponse, *apperror.AppError) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

res, err := s.client.FindByEmail(ctx, &checkinProto.FindByEmailCheckInRequest{
Email: req.Email,
})
if err != nil {
s.log.Named("FindByEmail").Error("FindByEmail: ", zap.Error(err))
st, ok := status.FromError(err)
if !ok {
return nil, apperror.InternalServer
}
switch st.Code() {
case codes.InvalidArgument:
return nil, apperror.BadRequest
case codes.Internal:
return nil, apperror.InternalServer
default:
return nil, apperror.ServiceUnavailable
}
}

return &dto.FindByEmailCheckInResponse{
CheckIns: ProtoToDtos(res.CheckIns),
}, nil
}

func (s *serviceImpl) FindByUserID(req *dto.FindByUserIdCheckInRequest) (*dto.FindByUserIdCheckInResponse, *apperror.AppError) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

res, err := s.client.FindByUserId(ctx, &checkinProto.FindByUserIdCheckInRequest{
UserId: req.UserID,
})
if err != nil {
s.log.Named("FindByUserID").Error("FindByUserID: ", zap.Error(err))
st, ok := status.FromError(err)
if !ok {
return nil, apperror.InternalServer
}
switch st.Code() {
case codes.InvalidArgument:
return nil, apperror.BadRequest
case codes.Internal:
return nil, apperror.InternalServer
default:
return nil, apperror.ServiceUnavailable
}
}

return &dto.FindByUserIdCheckInResponse{
CheckIns: ProtoToDtos(res.CheckIns),
}, nil
}
Loading

0 comments on commit f69c8a8

Please sign in to comment.