From 04a09371e2cf647208cd7567f8ffb2f6f55bedff Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:08:43 +0700 Subject: [PATCH 01/12] feat: make, docker --- Makefile | 7 +++ docker-compose.qa.yml | 108 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 docker-compose.qa.yml diff --git a/Makefile b/Makefile index a801d47..73fc8e3 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,15 @@ docker: docker-compose up +docker-qa: + docker-compose -f docker-compose.qa.yml up + server: go run cmd/main.go watch: air + mock-gen: mockgen -source ./internal/auth/auth.service.go -destination ./mocks/auth/auth.service.go mockgen -source ./internal/pin/pin.service.go -destination ./mocks/pin/pin.service.go @@ -23,5 +27,8 @@ test: proto: go get github.com/isd-sgcu/rpkm67-go-proto@latest +model: + go get github.com/isd-sgcu/rpkm67-model@latest + swagger: swag init -d ./internal/file -g ../../cmd/main.go -o ./docs -md ./docs/markdown --parseDependency --parseInternal \ No newline at end of file diff --git a/docker-compose.qa.yml b/docker-compose.qa.yml new file mode 100644 index 0000000..6a42fe5 --- /dev/null +++ b/docker-compose.qa.yml @@ -0,0 +1,108 @@ +version: "3.9" + +services: + auth: + image: ghcr.io/isd-sgcu/rpkm67-auth:914e1c9a6b3a8d2ac1b0a9ff4173076fc36d1df3 + container_name: auth + restart: unless-stopped + environment: + APP_PORT: 3002 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + REDIS_HOST: localhost + REDIS_PORT: 6379 + REDIS_PASSWORD: 5678 + JWT_SECRET: secret + JWT_ACCESS_TTL: 3600 + JWT_REFRESH_TTL: 259200 + JWT_ISSUER: issuer + JWT_RESET_TOKEN_TTL: 900 + OAUTH_CLIENT_ID: client_id + OAUTH_CLIENT_SECRET: client_secret + OAUTH_REDIRECT_URI: http://localhost:3000/auth/google/callback + networks: + - rpkm67 + ports: + - "3002:3002" + + backend: + image: ghcr.io/isd-sgcu/rpkm67-backend:40ca3d5cda65663fcc8c32ede5170a2dc456d7b9 + container_name: backend + restart: unless-stopped + environment: + APP_PORT: 3003 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + REDIS_HOST: cache + REDIS_PORT: 6379 + REDIS_PASSWORD: 5678 + PIN_WORKSHOP_CODE: workshop + PIN_WORKSHOP_COUNT: 5 + PIN_LANDMARK_CODE: landmark + PIN_LANDMARK_COUNT: 4 + networks: + - rpkm67 + ports: + - "3003:3003" + + checkin: + image: ghcr.io/isd-sgcu/rpkm67-checkin:718156635121b4d560c5d4d4f75fd9abdf3103cb + container_name: checkin + restart: unless-stopped + environment: + APP_PORT: 3004 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + networks: + - rpkm67 + ports: + - "3004:3004" + + store: + image: ghcr.io/isd-sgcu/rpkm67-store:a6f718f5556abfb44b10b178fba0db9f9dc717a1 + container_name: store + restart: unless-stopped + environment: + APP_PORT: 3005 + APP_ENV: development + APP_MAX_FILE_SIZE_MB: 20 + ENDPOINT: endpoint + ACCESS_KEY: access_key + SECRET_KEY: secret_key + USE_SSL: true + BUCKET_NAME: rpkm67-qa + networks: + - rpkm67 + ports: + - "3005:3005" + + db: + image: postgres:15.1-alpine3.17 + container_name: db + restart: unless-stopped + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: "1234" + POSTGRES_DB: rpkm67_db + networks: + - rpkm67 + volumes: + - ./volumes/postgres:/var/lib/postgresql/data + ports: + - "5432:5432" + + cache: + image: redis:7.2.3-alpine + container_name: cache + restart: unless-stopped + environment: + REDIS_HOST: localhost + REDIS_PASSWORD: "5678" + networks: + - rpkm67 + ports: + - "6379:6379" + +networks: + rpkm67: + name: rpkm67 From 2e557b39b877798af715aa8018affce2ae644726 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:12:49 +0700 Subject: [PATCH 02/12] feat: dtos --- go.mod | 3 +-- go.sum | 17 ++------------ internal/dto/checkin.dto.go | 34 ++++++++++++++++++++++++++++ internal/dto/user.dto.go | 45 +++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 internal/dto/checkin.dto.go create mode 100644 internal/dto/user.dto.go diff --git a/go.mod b/go.mod index 2fd203b..8a49d8d 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 github.com/isd-sgcu/rpkm67-go-proto v0.1.6 + github.com/isd-sgcu/rpkm67-model v0.0.4 github.com/joho/godotenv v1.5.1 github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 @@ -21,8 +22,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 diff --git a/go.sum b/go.sum index 319b16a..75cbcba 100644 --- a/go.sum +++ b/go.sum @@ -55,22 +55,10 @@ 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/isd-sgcu/rpkm67-model v0.0.4 h1:tk6z6pXnhWBoG2SaSIoyLxNnwRaXwdbSIEEa/cSi8EY= +github.com/isd-sgcu/rpkm67-model v0.0.4/go.mod h1:dxgLSkrFpbQOXsrzqgepZoEOyZUIG2LBGtm5gsuBbVc= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -111,7 +99,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= diff --git a/internal/dto/checkin.dto.go b/internal/dto/checkin.dto.go new file mode 100644 index 0000000..0943318 --- /dev/null +++ b/internal/dto/checkin.dto.go @@ -0,0 +1,34 @@ +package dto + +type CheckIn struct { + Id string `json:"id"` + Event string `json:"event"` + Email string `json:"email"` + UserId string `json:"user_id"` +} + +type CreateCheckInRequest struct { + Event string `json:"event" validate:"required"` + Email string `json:"email" validate:"required"` + UserId string `json:"user_id" validate:"required"` +} + +type CreateCheckInResponse struct { + CheckIn *CheckIn `json:"check_in"` +} + +type FindByUserIdCheckInRequest struct { + UserId string `json:"user_id" validate:"required"` +} + +type FindByUserIdCheckInResponse struct { + CheckIns []*CheckIn `json:"check_ins"` +} + +type FindByEmailCheckInRequest struct { + Email string `json:"email" validate:"required"` +} + +type FindByEmailCheckInResponse struct { + CheckIns []*CheckIn `json:"check_ins"` +} diff --git a/internal/dto/user.dto.go b/internal/dto/user.dto.go new file mode 100644 index 0000000..3293590 --- /dev/null +++ b/internal/dto/user.dto.go @@ -0,0 +1,45 @@ +package dto + +import ( + "github.com/google/uuid" + "github.com/isd-sgcu/rpkm67-model/constant" +) + +type User struct { + Id string `json:"id"` + Email string `json:"email"` + Nickname string `json:"nickname"` + Title string `json:"title"` + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Year int `json:"year"` + Faculty string `json:"faculty"` + Tel string `json:"tel"` + ParentTel string `json:"parent_tel"` + Parent string `json:"parent"` + FoodAllergy string `json:"food_allergy"` + DrugAllergy string `json:"drug_allergy"` + Illness string `json:"illness"` + Role constant.Role `json:"role"` + PhotoKey string `json:"photo_key"` + PhotoUrl string `json:"photo_url"` + Baan string `json:"baan"` + ReceiveGift int `json:"receive_gift"` + GroupID *uuid.UUID `json:"group_id"` + CheckIns []*CheckIn `json:"check_ins"` +} + +type FindOneUserRequest struct { + Id string `json:"id" validate:"required"` +} + +type FindOneUserResponse struct { + User *User `json:"user"` +} + +type UpdateUserRequest struct { +} + +type UpdateUserResponse struct { + User *User `json:"user"` +} From a38ae02922a18d4f3859e8ff6f7e61a5184b6395 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:12:59 +0700 Subject: [PATCH 03/12] pin tests --- internal/user/test/pin.handler_test.go | 88 ++++++++++++++++++ internal/user/test/pin.service_test.go | 93 ++++++++++++++++++++ internal/user/test/pin.service_test.utils.go | 31 +++++++ 3 files changed, 212 insertions(+) create mode 100644 internal/user/test/pin.handler_test.go create mode 100644 internal/user/test/pin.service_test.go create mode 100644 internal/user/test/pin.service_test.utils.go diff --git a/internal/user/test/pin.handler_test.go b/internal/user/test/pin.handler_test.go new file mode 100644 index 0000000..6ad5f11 --- /dev/null +++ b/internal/user/test/pin.handler_test.go @@ -0,0 +1,88 @@ +package test + +// import ( +// "net/http" +// "testing" + +// "github.com/golang/mock/gomock" +// "github.com/isd-sgcu/rpkm67-gateway/apperror" +// "github.com/isd-sgcu/rpkm67-gateway/internal/baan" +// "github.com/isd-sgcu/rpkm67-gateway/internal/dto" +// baanMock "github.com/isd-sgcu/rpkm67-gateway/mocks/baan" +// routerMock "github.com/isd-sgcu/rpkm67-gateway/mocks/router" +// validatorMock "github.com/isd-sgcu/rpkm67-gateway/mocks/validator" +// "github.com/stretchr/testify/suite" +// "go.uber.org/zap" +// ) + +// type BaanHandlerTest struct { +// suite.Suite +// controller *gomock.Controller +// logger *zap.Logger +// Baans []*dto.Baan +// Baan *dto.Baan +// FindAllBaanReq *dto.FindAllBaanRequest +// FindOneBaanReq *dto.FindOneBaanRequest +// Err *apperror.AppError +// ParamMock string +// } + +// func TestBaanHandler(t *testing.T) { +// suite.Run(t, new(BaanHandlerTest)) +// } + +// func (t *BaanHandlerTest) SetupTest() { +// t.controller = gomock.NewController(t.T()) +// t.logger = zap.NewNop() + +// baansProto := MockBaansProto() +// baanProto := baansProto[0] + +// t.Baans = baan.ProtoToDtoList(baansProto) +// t.Baan = baan.ProtoToDto(baanProto) + +// t.FindAllBaanReq = &dto.FindAllBaanRequest{} +// t.FindOneBaanReq = &dto.FindOneBaanRequest{ +// Id: t.Baan.Id, +// } + +// t.ParamMock = t.Baan.Id +// } + +// func (t *BaanHandlerTest) TestFindAllBaanSuccess() { +// baanSvc := baanMock.NewMockService(t.controller) +// validator := validatorMock.NewMockDtoValidator(t.controller) +// context := routerMock.NewMockContext(t.controller) +// handler := baan.NewHandler(baanSvc, validator, t.logger) + +// expectedResp := &dto.FindAllBaanResponse{ +// Baans: t.Baans, +// } + +// baanSvc.EXPECT().FindAllBaan(t.FindAllBaanReq).Return(expectedResp, t.Err) +// context.EXPECT().JSON(http.StatusOK, expectedResp) + +// handler.FindAllBaan(context) +// } + +// func (t *BaanHandlerTest) TestFindOneBaanSuccess() { +// baanSvc := baanMock.NewMockService(t.controller) +// validator := validatorMock.NewMockDtoValidator(t.controller) +// context := routerMock.NewMockContext(t.controller) +// handler := baan.NewHandler(baanSvc, validator, t.logger) + +// expectedResp := &dto.FindOneBaanResponse{ +// Baan: t.Baan, +// } + +// context.EXPECT().Param("id").Return(t.ParamMock) +// validator.EXPECT().Validate(t.FindOneBaanReq).Return(nil) +// baanSvc.EXPECT().FindOneBaan(t.FindOneBaanReq).Return(expectedResp, t.Err) +// context.EXPECT().JSON(http.StatusOK, expectedResp) + +// handler.FindOneBaan(context) +// } + +// func (t *BaanHandlerTest) TearDownTest() { +// t.controller.Finish() +// } diff --git a/internal/user/test/pin.service_test.go b/internal/user/test/pin.service_test.go new file mode 100644 index 0000000..0d380f4 --- /dev/null +++ b/internal/user/test/pin.service_test.go @@ -0,0 +1,93 @@ +package test + +// import ( +// "testing" + +// "github.com/golang/mock/gomock" +// "github.com/isd-sgcu/rpkm67-gateway/apperror" +// "github.com/isd-sgcu/rpkm67-gateway/internal/baan" +// "github.com/isd-sgcu/rpkm67-gateway/internal/dto" +// baanMock "github.com/isd-sgcu/rpkm67-gateway/mocks/client/baan" +// baanProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/baan/v1" +// "github.com/stretchr/testify/suite" +// "go.uber.org/zap" +// ) + +// type BaanServiceTest struct { +// suite.Suite +// controller *gomock.Controller +// logger *zap.Logger +// BaansProto []*baanProto.Baan +// BaanProto *baanProto.Baan +// BaansDto []*dto.Baan +// BaanDto *dto.Baan +// FindAllBaanProtoReq *baanProto.FindAllBaanRequest +// FindAllBaanDtoReq *dto.FindAllBaanRequest +// FindOneBaanProtoReq *baanProto.FindOneBaanRequest +// FindOneBaanDtoReq *dto.FindOneBaanRequest +// Err apperror.AppError +// } + +// func TestBaanService(t *testing.T) { +// suite.Run(t, new(BaanServiceTest)) +// } + +// func (t *BaanServiceTest) SetupTest() { +// t.controller = gomock.NewController(t.T()) +// t.logger = zap.NewNop() + +// t.BaansProto = MockBaansProto() +// t.BaanProto = t.BaansProto[0] +// t.BaansDto = baan.ProtoToDtoList(t.BaansProto) +// t.BaanDto = baan.ProtoToDto(t.BaanProto) + +// t.FindAllBaanProtoReq = &baanProto.FindAllBaanRequest{} +// t.FindOneBaanProtoReq = &baanProto.FindOneBaanRequest{ +// Id: t.BaanProto.Id, +// } +// t.FindAllBaanDtoReq = &dto.FindAllBaanRequest{} +// t.FindOneBaanDtoReq = &dto.FindOneBaanRequest{ +// Id: t.BaanDto.Id, +// } +// } + +// func (t *BaanServiceTest) TestFindAllBaanSuccess() { +// client := baanMock.BaanClientMock{} +// svc := baan.NewService(&client, t.logger) + +// protoResp := &baanProto.FindAllBaanResponse{ +// Baans: t.BaansProto, +// } +// findAllBaansDto := baan.ProtoToDtoList(protoResp.Baans) +// expected := &dto.FindAllBaanResponse{ +// Baans: findAllBaansDto, +// } + +// client.On("FindAllBaan", t.FindAllBaanProtoReq).Return(protoResp, nil) +// actual, err := svc.FindAllBaan(t.FindAllBaanDtoReq) + +// t.Nil(err) +// t.Equal(expected, actual) +// } + +// func (t *BaanServiceTest) TestFindOneBaanSuccess() { +// client := baanMock.BaanClientMock{} +// svc := baan.NewService(&client, t.logger) + +// protoResp := &baanProto.FindOneBaanResponse{ +// Baan: t.BaanProto, +// } +// expected := &dto.FindOneBaanResponse{ +// Baan: t.BaanDto, +// } + +// client.On("FindOneBaan", t.FindOneBaanProtoReq).Return(protoResp, nil) +// actual, err := svc.FindOneBaan(t.FindOneBaanDtoReq) + +// t.Nil(err) +// t.Equal(expected, actual) +// } + +// func (t *BaanServiceTest) TearDownTest() { +// t.controller.Finish() +// } diff --git a/internal/user/test/pin.service_test.utils.go b/internal/user/test/pin.service_test.utils.go new file mode 100644 index 0000000..acdd1a5 --- /dev/null +++ b/internal/user/test/pin.service_test.utils.go @@ -0,0 +1,31 @@ +package test + +// import ( +// "math/rand" + +// "github.com/bxcodec/faker/v4" +// baanProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/baan/v1" +// ) + +// func MockBaansProto() []*baanProto.Baan { +// var baans []*baanProto.Baan +// for i := 0; i < 10; i++ { +// baan := &baanProto.Baan{ +// Id: faker.UUIDHyphenated(), +// NameTH: faker.Name(), +// DescriptionTH: faker.Sentence(), +// NameEN: faker.Name(), +// DescriptionEN: faker.Sentence(), +// Size: baanProto.BaanSize(rand.Intn(6)), +// Facebook: faker.URL(), +// FacebookUrl: faker.URL(), +// Instagram: faker.URL(), +// InstagramUrl: faker.URL(), +// Line: faker.URL(), +// LineUrl: faker.URL(), +// ImageUrl: faker.URL(), +// } +// baans = append(baans, baan) +// } +// return baans +// } From a3614222f0b785b9de11b238626a5e37ff528135 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:13:07 +0700 Subject: [PATCH 04/12] user --- internal/user/user.handler.go | 68 ++++++++++++++++++++++++++++ internal/user/user.service.go | 84 +++++++++++++++++++++++++++++++++++ internal/user/user.utils.go | 21 +++++++++ 3 files changed, 173 insertions(+) create mode 100644 internal/user/user.handler.go create mode 100644 internal/user/user.service.go create mode 100644 internal/user/user.utils.go diff --git a/internal/user/user.handler.go b/internal/user/user.handler.go new file mode 100644 index 0000000..ad46025 --- /dev/null +++ b/internal/user/user.handler.go @@ -0,0 +1,68 @@ +package pin + +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 { + FindAll(c router.Context) + ResetPin(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) FindAll(c router.Context) { + req := &dto.FindAllPinRequest{} + res, appErr := h.svc.FindAll(req) + if appErr != nil { + h.log.Named("FindAll").Error("FindAll: ", zap.Error(appErr)) + c.ResponseError(appErr) + return + } + + c.JSON(http.StatusOK, &dto.FindAllPinResponse{Pins: res.Pins}) +} + +func (h *handlerImpl) ResetPin(c router.Context) { + workshopId := c.Param("workshop-id") + if workshopId == "" { + c.BadRequestError("url parameter 'workshop-id' not found") + } + + req := &dto.ResetPinRequest{ + WorkshopId: workshopId, + } + + if errorList := h.validate.Validate(req); errorList != nil { + h.log.Named("ResetPin").Error("Validate: ", zap.Strings("errorList", errorList)) + c.BadRequestError(strings.Join(errorList, ", ")) + return + } + + res, appErr := h.svc.ResetPin(req) + if appErr != nil { + h.log.Named("ResetPin").Error("ResetPin: ", zap.Error(appErr)) + c.ResponseError(appErr) + return + } + + c.JSON(http.StatusOK, &dto.ResetPinResponse{Success: res.Success}) +} diff --git a/internal/user/user.service.go b/internal/user/user.service.go new file mode 100644 index 0000000..13acd81 --- /dev/null +++ b/internal/user/user.service.go @@ -0,0 +1,84 @@ +package pin + +import ( + "context" + "time" + + "github.com/isd-sgcu/rpkm67-gateway/apperror" + "github.com/isd-sgcu/rpkm67-gateway/internal/dto" + pinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/pin/v1" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type Service interface { + FindAll(req *dto.FindAllPinRequest) (*dto.FindAllPinResponse, *apperror.AppError) + ResetPin(req *dto.ResetPinRequest) (*dto.ResetPinResponse, *apperror.AppError) +} + +type serviceImpl struct { + client pinProto.PinServiceClient + log *zap.Logger +} + +func NewService(client pinProto.PinServiceClient, log *zap.Logger) Service { + return &serviceImpl{ + client: client, + log: log, + } +} + +func (s *serviceImpl) FindAll(req *dto.FindAllPinRequest) (*dto.FindAllPinResponse, *apperror.AppError) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + res, err := s.client.FindAll(ctx, &pinProto.FindAllPinRequest{}) + if err != nil { + s.log.Named("FindAllBaan").Error("FindAllBaan: ", zap.Error(err)) + st, ok := status.FromError(err) + if !ok { + return nil, apperror.InternalServer + } + switch st.Code() { + case codes.InvalidArgument: + return nil, apperror.BadRequestError("Invalid argument") + case codes.Internal: + return nil, apperror.InternalServerError(err.Error()) + default: + return nil, apperror.ServiceUnavailable + } + } + + return &dto.FindAllPinResponse{ + Pins: ProtoToDtoList(res.Pins), + }, nil +} + +func (s *serviceImpl) ResetPin(req *dto.ResetPinRequest) (*dto.ResetPinResponse, *apperror.AppError) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + res, err := s.client.ResetPin(ctx, &pinProto.ResetPinRequest{ + WorkshopId: req.WorkshopId, + }) + if err != nil { + s.log.Named("FindOneBaan").Error("FindOneBaan: ", zap.Error(err)) + st, ok := status.FromError(err) + if !ok { + return nil, apperror.InternalServer + } + switch st.Code() { + case codes.NotFound: + return nil, apperror.NotFoundError("Pin not found") + case codes.Internal: + return nil, apperror.InternalServerError(err.Error()) + default: + return nil, apperror.ServiceUnavailable + } + } + + return &dto.ResetPinResponse{ + Success: res.Success, + }, nil +} diff --git a/internal/user/user.utils.go b/internal/user/user.utils.go new file mode 100644 index 0000000..9f47cd2 --- /dev/null +++ b/internal/user/user.utils.go @@ -0,0 +1,21 @@ +package pin + +import ( + "github.com/isd-sgcu/rpkm67-gateway/internal/dto" + pinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/pin/v1" +) + +func ProtoToDto(in *pinProto.Pin) *dto.Pin { + return &dto.Pin{ + WorkshopId: in.WorkshopId, + Code: in.Code, + } +} + +func ProtoToDtoList(in []*pinProto.Pin) []*dto.Pin { + var out []*dto.Pin + for _, b := range in { + out = append(out, ProtoToDto(b)) + } + return out +} From f3edb441a7d8547e2f5a5ca08f05f7f95c01f83c Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:46:02 +0700 Subject: [PATCH 05/12] user --- internal/dto/user.dto.go | 41 ++++++++- internal/user/test/pin.handler_test.go | 88 ------------------ internal/user/test/pin.service_test.go | 93 -------------------- internal/user/test/pin.service_test.utils.go | 31 ------- internal/user/test/user.handler_test.go | 32 +++++++ internal/user/test/user.service_test.go | 32 +++++++ internal/user/user.handler.go | 78 ++++++++++++---- internal/user/user.service.go | 63 +++++++++---- internal/user/user.utils.go | 36 +++++--- 9 files changed, 228 insertions(+), 266 deletions(-) delete mode 100644 internal/user/test/pin.handler_test.go delete mode 100644 internal/user/test/pin.service_test.go delete mode 100644 internal/user/test/pin.service_test.utils.go create mode 100644 internal/user/test/user.handler_test.go create mode 100644 internal/user/test/user.service_test.go diff --git a/internal/dto/user.dto.go b/internal/dto/user.dto.go index 3293590..e60d23f 100644 --- a/internal/dto/user.dto.go +++ b/internal/dto/user.dto.go @@ -1,7 +1,6 @@ package dto import ( - "github.com/google/uuid" "github.com/isd-sgcu/rpkm67-model/constant" ) @@ -25,7 +24,7 @@ type User struct { PhotoUrl string `json:"photo_url"` Baan string `json:"baan"` ReceiveGift int `json:"receive_gift"` - GroupID *uuid.UUID `json:"group_id"` + GroupId string `json:"group_id"` CheckIns []*CheckIn `json:"check_ins"` } @@ -37,7 +36,45 @@ type FindOneUserResponse struct { User *User `json:"user"` } +type UpdateUserRequestBody struct { + Nickname string `json:"nickname"` + Title string `json:"title"` + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Year int `json:"year"` + Faculty string `json:"faculty"` + Tel string `json:"tel"` + ParentTel string `json:"parent_tel"` + Parent string `json:"parent"` + FoodAllergy string `json:"food_allergy"` + DrugAllergy string `json:"drug_allergy"` + Illness string `json:"illness"` + PhotoKey string `json:"photo_key"` + PhotoUrl string `json:"photo_url"` + Baan string `json:"baan"` + ReceiveGift int `json:"receive_gift"` + GroupId string `json:"group_id"` +} + type UpdateUserRequest struct { + Id string `json:"id" validate:"required"` + Nickname string `json:"nickname"` + Title string `json:"title"` + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Year int `json:"year"` + Faculty string `json:"faculty"` + Tel string `json:"tel"` + ParentTel string `json:"parent_tel"` + Parent string `json:"parent"` + FoodAllergy string `json:"food_allergy"` + DrugAllergy string `json:"drug_allergy"` + Illness string `json:"illness"` + PhotoKey string `json:"photo_key"` + PhotoUrl string `json:"photo_url"` + Baan string `json:"baan"` + ReceiveGift int `json:"receive_gift"` + GroupId string `json:"group_id"` } type UpdateUserResponse struct { diff --git a/internal/user/test/pin.handler_test.go b/internal/user/test/pin.handler_test.go deleted file mode 100644 index 6ad5f11..0000000 --- a/internal/user/test/pin.handler_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package test - -// import ( -// "net/http" -// "testing" - -// "github.com/golang/mock/gomock" -// "github.com/isd-sgcu/rpkm67-gateway/apperror" -// "github.com/isd-sgcu/rpkm67-gateway/internal/baan" -// "github.com/isd-sgcu/rpkm67-gateway/internal/dto" -// baanMock "github.com/isd-sgcu/rpkm67-gateway/mocks/baan" -// routerMock "github.com/isd-sgcu/rpkm67-gateway/mocks/router" -// validatorMock "github.com/isd-sgcu/rpkm67-gateway/mocks/validator" -// "github.com/stretchr/testify/suite" -// "go.uber.org/zap" -// ) - -// type BaanHandlerTest struct { -// suite.Suite -// controller *gomock.Controller -// logger *zap.Logger -// Baans []*dto.Baan -// Baan *dto.Baan -// FindAllBaanReq *dto.FindAllBaanRequest -// FindOneBaanReq *dto.FindOneBaanRequest -// Err *apperror.AppError -// ParamMock string -// } - -// func TestBaanHandler(t *testing.T) { -// suite.Run(t, new(BaanHandlerTest)) -// } - -// func (t *BaanHandlerTest) SetupTest() { -// t.controller = gomock.NewController(t.T()) -// t.logger = zap.NewNop() - -// baansProto := MockBaansProto() -// baanProto := baansProto[0] - -// t.Baans = baan.ProtoToDtoList(baansProto) -// t.Baan = baan.ProtoToDto(baanProto) - -// t.FindAllBaanReq = &dto.FindAllBaanRequest{} -// t.FindOneBaanReq = &dto.FindOneBaanRequest{ -// Id: t.Baan.Id, -// } - -// t.ParamMock = t.Baan.Id -// } - -// func (t *BaanHandlerTest) TestFindAllBaanSuccess() { -// baanSvc := baanMock.NewMockService(t.controller) -// validator := validatorMock.NewMockDtoValidator(t.controller) -// context := routerMock.NewMockContext(t.controller) -// handler := baan.NewHandler(baanSvc, validator, t.logger) - -// expectedResp := &dto.FindAllBaanResponse{ -// Baans: t.Baans, -// } - -// baanSvc.EXPECT().FindAllBaan(t.FindAllBaanReq).Return(expectedResp, t.Err) -// context.EXPECT().JSON(http.StatusOK, expectedResp) - -// handler.FindAllBaan(context) -// } - -// func (t *BaanHandlerTest) TestFindOneBaanSuccess() { -// baanSvc := baanMock.NewMockService(t.controller) -// validator := validatorMock.NewMockDtoValidator(t.controller) -// context := routerMock.NewMockContext(t.controller) -// handler := baan.NewHandler(baanSvc, validator, t.logger) - -// expectedResp := &dto.FindOneBaanResponse{ -// Baan: t.Baan, -// } - -// context.EXPECT().Param("id").Return(t.ParamMock) -// validator.EXPECT().Validate(t.FindOneBaanReq).Return(nil) -// baanSvc.EXPECT().FindOneBaan(t.FindOneBaanReq).Return(expectedResp, t.Err) -// context.EXPECT().JSON(http.StatusOK, expectedResp) - -// handler.FindOneBaan(context) -// } - -// func (t *BaanHandlerTest) TearDownTest() { -// t.controller.Finish() -// } diff --git a/internal/user/test/pin.service_test.go b/internal/user/test/pin.service_test.go deleted file mode 100644 index 0d380f4..0000000 --- a/internal/user/test/pin.service_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package test - -// import ( -// "testing" - -// "github.com/golang/mock/gomock" -// "github.com/isd-sgcu/rpkm67-gateway/apperror" -// "github.com/isd-sgcu/rpkm67-gateway/internal/baan" -// "github.com/isd-sgcu/rpkm67-gateway/internal/dto" -// baanMock "github.com/isd-sgcu/rpkm67-gateway/mocks/client/baan" -// baanProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/baan/v1" -// "github.com/stretchr/testify/suite" -// "go.uber.org/zap" -// ) - -// type BaanServiceTest struct { -// suite.Suite -// controller *gomock.Controller -// logger *zap.Logger -// BaansProto []*baanProto.Baan -// BaanProto *baanProto.Baan -// BaansDto []*dto.Baan -// BaanDto *dto.Baan -// FindAllBaanProtoReq *baanProto.FindAllBaanRequest -// FindAllBaanDtoReq *dto.FindAllBaanRequest -// FindOneBaanProtoReq *baanProto.FindOneBaanRequest -// FindOneBaanDtoReq *dto.FindOneBaanRequest -// Err apperror.AppError -// } - -// func TestBaanService(t *testing.T) { -// suite.Run(t, new(BaanServiceTest)) -// } - -// func (t *BaanServiceTest) SetupTest() { -// t.controller = gomock.NewController(t.T()) -// t.logger = zap.NewNop() - -// t.BaansProto = MockBaansProto() -// t.BaanProto = t.BaansProto[0] -// t.BaansDto = baan.ProtoToDtoList(t.BaansProto) -// t.BaanDto = baan.ProtoToDto(t.BaanProto) - -// t.FindAllBaanProtoReq = &baanProto.FindAllBaanRequest{} -// t.FindOneBaanProtoReq = &baanProto.FindOneBaanRequest{ -// Id: t.BaanProto.Id, -// } -// t.FindAllBaanDtoReq = &dto.FindAllBaanRequest{} -// t.FindOneBaanDtoReq = &dto.FindOneBaanRequest{ -// Id: t.BaanDto.Id, -// } -// } - -// func (t *BaanServiceTest) TestFindAllBaanSuccess() { -// client := baanMock.BaanClientMock{} -// svc := baan.NewService(&client, t.logger) - -// protoResp := &baanProto.FindAllBaanResponse{ -// Baans: t.BaansProto, -// } -// findAllBaansDto := baan.ProtoToDtoList(protoResp.Baans) -// expected := &dto.FindAllBaanResponse{ -// Baans: findAllBaansDto, -// } - -// client.On("FindAllBaan", t.FindAllBaanProtoReq).Return(protoResp, nil) -// actual, err := svc.FindAllBaan(t.FindAllBaanDtoReq) - -// t.Nil(err) -// t.Equal(expected, actual) -// } - -// func (t *BaanServiceTest) TestFindOneBaanSuccess() { -// client := baanMock.BaanClientMock{} -// svc := baan.NewService(&client, t.logger) - -// protoResp := &baanProto.FindOneBaanResponse{ -// Baan: t.BaanProto, -// } -// expected := &dto.FindOneBaanResponse{ -// Baan: t.BaanDto, -// } - -// client.On("FindOneBaan", t.FindOneBaanProtoReq).Return(protoResp, nil) -// actual, err := svc.FindOneBaan(t.FindOneBaanDtoReq) - -// t.Nil(err) -// t.Equal(expected, actual) -// } - -// func (t *BaanServiceTest) TearDownTest() { -// t.controller.Finish() -// } diff --git a/internal/user/test/pin.service_test.utils.go b/internal/user/test/pin.service_test.utils.go deleted file mode 100644 index acdd1a5..0000000 --- a/internal/user/test/pin.service_test.utils.go +++ /dev/null @@ -1,31 +0,0 @@ -package test - -// import ( -// "math/rand" - -// "github.com/bxcodec/faker/v4" -// baanProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/baan/v1" -// ) - -// func MockBaansProto() []*baanProto.Baan { -// var baans []*baanProto.Baan -// for i := 0; i < 10; i++ { -// baan := &baanProto.Baan{ -// Id: faker.UUIDHyphenated(), -// NameTH: faker.Name(), -// DescriptionTH: faker.Sentence(), -// NameEN: faker.Name(), -// DescriptionEN: faker.Sentence(), -// Size: baanProto.BaanSize(rand.Intn(6)), -// Facebook: faker.URL(), -// FacebookUrl: faker.URL(), -// Instagram: faker.URL(), -// InstagramUrl: faker.URL(), -// Line: faker.URL(), -// LineUrl: faker.URL(), -// ImageUrl: faker.URL(), -// } -// baans = append(baans, baan) -// } -// return baans -// } diff --git a/internal/user/test/user.handler_test.go b/internal/user/test/user.handler_test.go new file mode 100644 index 0000000..dd0c0c5 --- /dev/null +++ b/internal/user/test/user.handler_test.go @@ -0,0 +1,32 @@ +package test + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" +) + +type UserHandlerTest struct { + suite.Suite + controller *gomock.Controller + logger *zap.Logger +} + +func TestUserHandler(t *testing.T) { + suite.Run(t, new(UserHandlerTest)) +} + +func (t *UserHandlerTest) SetupTest() { + t.controller = gomock.NewController(t.T()) + t.logger = zap.NewNop() +} + +func (t *UserHandlerTest) TestFindOneUserSuccess() { + +} + +func (t *UserHandlerTest) TearDownTest() { + t.controller.Finish() +} diff --git a/internal/user/test/user.service_test.go b/internal/user/test/user.service_test.go new file mode 100644 index 0000000..e357669 --- /dev/null +++ b/internal/user/test/user.service_test.go @@ -0,0 +1,32 @@ +package test + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" +) + +type UserServiceTest struct { + suite.Suite + controller *gomock.Controller + logger *zap.Logger +} + +func TestUserService(t *testing.T) { + suite.Run(t, new(UserServiceTest)) +} + +func (t *UserServiceTest) SetupTest() { + t.controller = gomock.NewController(t.T()) + t.logger = zap.NewNop() +} + +func (t *UserServiceTest) TestFindOneUserSuccess() { + +} + +func (t *UserServiceTest) TearDownTest() { + t.controller.Finish() +} diff --git a/internal/user/user.handler.go b/internal/user/user.handler.go index ad46025..290dec1 100644 --- a/internal/user/user.handler.go +++ b/internal/user/user.handler.go @@ -1,4 +1,4 @@ -package pin +package user import ( "net/http" @@ -11,8 +11,8 @@ import ( ) type Handler interface { - FindAll(c router.Context) - ResetPin(c router.Context) + FindOne(c router.Context) + Update(c router.Context) } func NewHandler(svc Service, validate validator.DtoValidator, log *zap.Logger) Handler { @@ -29,40 +29,80 @@ type handlerImpl struct { log *zap.Logger } -func (h *handlerImpl) FindAll(c router.Context) { - req := &dto.FindAllPinRequest{} - res, appErr := h.svc.FindAll(req) +func (h *handlerImpl) FindOne(c router.Context) { + id := c.Param("id") + if id == "" { + h.log.Named("FindOne").Error("Param: id not found") + c.BadRequestError("url parameter 'id' not found") + return + } + + req := &dto.FindOneUserRequest{ + Id: id, + } + + res, appErr := h.svc.FindOne(req) if appErr != nil { - h.log.Named("FindAll").Error("FindAll: ", zap.Error(appErr)) + h.log.Named("FindOne").Error("FindOne: ", zap.Error(appErr)) c.ResponseError(appErr) return } - c.JSON(http.StatusOK, &dto.FindAllPinResponse{Pins: res.Pins}) + c.JSON(http.StatusOK, &dto.FindOneUserResponse{User: res.User}) } -func (h *handlerImpl) ResetPin(c router.Context) { - workshopId := c.Param("workshop-id") - if workshopId == "" { - c.BadRequestError("url parameter 'workshop-id' not found") +func (h *handlerImpl) Update(c router.Context) { + id := c.Param("id") + if id == "" { + h.log.Named("Update").Error("Param: id not found") + c.BadRequestError("url parameter 'id' not found") + return } - req := &dto.ResetPinRequest{ - WorkshopId: workshopId, + body := &dto.UpdateUserRequestBody{} + if err := c.Bind(body); err != nil { + h.log.Named("Update").Error("Bind: failed to bind request body", zap.Error(err)) + c.BadRequestError("Bind: failed to bind request body") + return } - if errorList := h.validate.Validate(req); errorList != nil { - h.log.Named("ResetPin").Error("Validate: ", zap.Strings("errorList", errorList)) + if errorList := h.validate.Validate(body); errorList != nil { + h.log.Named("Update").Error("Validate: ", zap.Strings("errorList", errorList)) c.BadRequestError(strings.Join(errorList, ", ")) return } - res, appErr := h.svc.ResetPin(req) + req := h.createUpdateUserRequestDto(id, body) + + res, appErr := h.svc.Update(req) if appErr != nil { - h.log.Named("ResetPin").Error("ResetPin: ", zap.Error(appErr)) + h.log.Named("Update").Error("Update: ", zap.Error(appErr)) c.ResponseError(appErr) return } - c.JSON(http.StatusOK, &dto.ResetPinResponse{Success: res.Success}) + c.JSON(http.StatusOK, &dto.UpdateUserResponse{User: res.User}) +} + +func (h *handlerImpl) createUpdateUserRequestDto(id string, body *dto.UpdateUserRequestBody) *dto.UpdateUserRequest { + return &dto.UpdateUserRequest{ + Id: id, + Nickname: body.Nickname, + Title: body.Title, + Firstname: body.Firstname, + Lastname: body.Lastname, + Year: body.Year, + Faculty: body.Faculty, + Tel: body.Tel, + ParentTel: body.ParentTel, + Parent: body.Parent, + FoodAllergy: body.FoodAllergy, + DrugAllergy: body.DrugAllergy, + Illness: body.Illness, + PhotoKey: body.PhotoKey, + PhotoUrl: body.PhotoUrl, + Baan: body.Baan, + ReceiveGift: body.ReceiveGift, + GroupId: body.GroupId, + } } diff --git a/internal/user/user.service.go b/internal/user/user.service.go index 13acd81..f2bd04b 100644 --- a/internal/user/user.service.go +++ b/internal/user/user.service.go @@ -1,4 +1,4 @@ -package pin +package user import ( "context" @@ -6,36 +6,38 @@ import ( "github.com/isd-sgcu/rpkm67-gateway/apperror" "github.com/isd-sgcu/rpkm67-gateway/internal/dto" - pinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/pin/v1" + userProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/auth/user/v1" "go.uber.org/zap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type Service interface { - FindAll(req *dto.FindAllPinRequest) (*dto.FindAllPinResponse, *apperror.AppError) - ResetPin(req *dto.ResetPinRequest) (*dto.ResetPinResponse, *apperror.AppError) + FindOne(req *dto.FindOneUserRequest) (*dto.FindOneUserResponse, *apperror.AppError) + Update(req *dto.UpdateUserRequest) (*dto.UpdateUserResponse, *apperror.AppError) } type serviceImpl struct { - client pinProto.PinServiceClient + client userProto.UserServiceClient log *zap.Logger } -func NewService(client pinProto.PinServiceClient, log *zap.Logger) Service { +func NewService(client userProto.UserServiceClient, log *zap.Logger) Service { return &serviceImpl{ client: client, log: log, } } -func (s *serviceImpl) FindAll(req *dto.FindAllPinRequest) (*dto.FindAllPinResponse, *apperror.AppError) { +func (s *serviceImpl) FindOne(req *dto.FindOneUserRequest) (*dto.FindOneUserResponse, *apperror.AppError) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - res, err := s.client.FindAll(ctx, &pinProto.FindAllPinRequest{}) + res, err := s.client.FindOne(ctx, &userProto.FindOneUserRequest{ + Id: req.Id, + }) if err != nil { - s.log.Named("FindAllBaan").Error("FindAllBaan: ", zap.Error(err)) + s.log.Named("FindOne").Error("FindOne: ", zap.Error(err)) st, ok := status.FromError(err) if !ok { return nil, apperror.InternalServer @@ -50,27 +52,27 @@ func (s *serviceImpl) FindAll(req *dto.FindAllPinRequest) (*dto.FindAllPinRespon } } - return &dto.FindAllPinResponse{ - Pins: ProtoToDtoList(res.Pins), + return &dto.FindOneUserResponse{ + User: ProtoToDto(res.User), }, nil } -func (s *serviceImpl) ResetPin(req *dto.ResetPinRequest) (*dto.ResetPinResponse, *apperror.AppError) { +func (s *serviceImpl) Update(req *dto.UpdateUserRequest) (*dto.UpdateUserResponse, *apperror.AppError) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - res, err := s.client.ResetPin(ctx, &pinProto.ResetPinRequest{ - WorkshopId: req.WorkshopId, - }) + updateReq := s.createUpdateUserRequestProto(req) + + res, err := s.client.Update(ctx, updateReq) if err != nil { - s.log.Named("FindOneBaan").Error("FindOneBaan: ", zap.Error(err)) + s.log.Named("Update").Error("Update: ", zap.Error(err)) st, ok := status.FromError(err) if !ok { return nil, apperror.InternalServer } switch st.Code() { case codes.NotFound: - return nil, apperror.NotFoundError("Pin not found") + return nil, apperror.NotFoundError("User not found") case codes.Internal: return nil, apperror.InternalServerError(err.Error()) default: @@ -78,7 +80,30 @@ func (s *serviceImpl) ResetPin(req *dto.ResetPinRequest) (*dto.ResetPinResponse, } } - return &dto.ResetPinResponse{ - Success: res.Success, + return &dto.UpdateUserResponse{ + User: ProtoToDto(res.User), }, nil } + +func (s *serviceImpl) createUpdateUserRequestProto(req *dto.UpdateUserRequest) *userProto.UpdateUserRequest { + return &userProto.UpdateUserRequest{ + Id: req.Id, + Nickname: req.Nickname, + Title: req.Title, + Firstname: req.Firstname, + Lastname: req.Lastname, + Year: int32(req.Year), + Faculty: req.Faculty, + Tel: req.Tel, + ParentTel: req.ParentTel, + Parent: req.Parent, + FoodAllergy: req.FoodAllergy, + DrugAllergy: req.DrugAllergy, + Illness: req.Illness, + PhotoKey: req.PhotoKey, + PhotoUrl: req.PhotoUrl, + Baan: req.Baan, + ReceiveGift: int32(req.ReceiveGift), + GroupId: req.GroupId, + } +} diff --git a/internal/user/user.utils.go b/internal/user/user.utils.go index 9f47cd2..9f51bbf 100644 --- a/internal/user/user.utils.go +++ b/internal/user/user.utils.go @@ -1,21 +1,29 @@ -package pin +package user import ( "github.com/isd-sgcu/rpkm67-gateway/internal/dto" - pinProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/backend/pin/v1" + userProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/auth/user/v1" ) -func ProtoToDto(in *pinProto.Pin) *dto.Pin { - return &dto.Pin{ - WorkshopId: in.WorkshopId, - Code: in.Code, +func ProtoToDto(in *userProto.User) *dto.User { + return &dto.User{ + Id: in.Id, + Nickname: in.Nickname, + Title: in.Title, + Firstname: in.Firstname, + Lastname: in.Lastname, + Year: int(in.Year), + Faculty: in.Faculty, + Tel: in.Tel, + ParentTel: in.ParentTel, + Parent: in.Parent, + FoodAllergy: in.FoodAllergy, + DrugAllergy: in.DrugAllergy, + Illness: in.Illness, + PhotoKey: in.PhotoKey, + PhotoUrl: in.PhotoUrl, + Baan: in.Baan, + ReceiveGift: int(in.ReceiveGift), + GroupId: in.GroupId, } } - -func ProtoToDtoList(in []*pinProto.Pin) []*dto.Pin { - var out []*dto.Pin - for _, b := range in { - out = append(out, ProtoToDto(b)) - } - return out -} From 10617003a35e8c069c13cde41dfcced55c20b7fb Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 28 Jun 2024 22:56:05 +0700 Subject: [PATCH 06/12] router, main --- cmd/main.go | 10 ++++++++++ internal/pin/pin.handler.go | 12 ++++++------ internal/router/v1.router.go | 12 ++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 6b09744..5505cbe 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -6,10 +6,12 @@ import ( "github.com/isd-sgcu/rpkm67-gateway/config" auth "github.com/isd-sgcu/rpkm67-gateway/internal/auth" "github.com/isd-sgcu/rpkm67-gateway/internal/router" + "github.com/isd-sgcu/rpkm67-gateway/internal/user" "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" + userProto "github.com/isd-sgcu/rpkm67-go-proto/rpkm67/auth/user/v1" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) @@ -38,12 +40,20 @@ func main() { authSvc := auth.NewService(authClient, logger) authHdr := auth.NewHandler(authSvc, validate, logger) + userClient := userProto.NewUserServiceClient(authConn) + userSvc := user.NewService(userClient, logger) + userHdr := user.NewHandler(userSvc, 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.V1Get("/user/:id", userHdr.FindOne) + r.V1Patch("/user/profile/:id", userHdr.UpdateProfile) + r.V1Put("/user/picture/:id", userHdr.UpdatePicture) + if err := r.Run(fmt.Sprintf(":%v", conf.App.Port)); err != nil { logger.Fatal("unable to start server") } diff --git a/internal/pin/pin.handler.go b/internal/pin/pin.handler.go index ad46025..808ed79 100644 --- a/internal/pin/pin.handler.go +++ b/internal/pin/pin.handler.go @@ -15,6 +15,12 @@ type Handler interface { ResetPin(c router.Context) } +type handlerImpl struct { + svc Service + validate validator.DtoValidator + log *zap.Logger +} + func NewHandler(svc Service, validate validator.DtoValidator, log *zap.Logger) Handler { return &handlerImpl{ svc: svc, @@ -23,12 +29,6 @@ func NewHandler(svc Service, validate validator.DtoValidator, log *zap.Logger) H } } -type handlerImpl struct { - svc Service - validate validator.DtoValidator - log *zap.Logger -} - func (h *handlerImpl) FindAll(c router.Context) { req := &dto.FindAllPinRequest{} res, appErr := h.svc.FindAll(req) diff --git a/internal/router/v1.router.go b/internal/router/v1.router.go index 4064b3e..cb5e7ce 100644 --- a/internal/router/v1.router.go +++ b/internal/router/v1.router.go @@ -14,6 +14,18 @@ func (r *Router) V1Post(path string, handler func(c Context)) { }) } +func (r *Router) V1Put(path string, handler func(c Context)) { + r.v1.PUT(path, func(c *gin.Context) { + handler(NewContext(c)) + }) +} + +func (r *Router) V1Patch(path string, handler func(c Context)) { + r.v1.PATCH(path, func(c *gin.Context) { + handler(NewContext(c)) + }) +} + func (r *Router) V1Delete(path string, handler func(c Context)) { r.v1.DELETE(path, func(c *gin.Context) { handler(NewContext(c)) From 71321c25f7cde5f837e0b81ed5b8a4c9cc4e3976 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 00:15:58 +0700 Subject: [PATCH 07/12] add maxfilesize + allowtype --- .env.template | 1 + cmd/main.go | 3 ++- config/config.go | 16 ++++++++++++---- constant/user.constants.go | 9 +++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 constant/user.constants.go diff --git a/.env.template b/.env.template index 9f01aa6..4d28e12 100644 --- a/.env.template +++ b/.env.template @@ -1,5 +1,6 @@ APP_PORT=3001 APP_ENV=development +APP_MAX_FILE_SIZE_MB=10 SERVICE_AUTH=auth:3002 SERVICE_BACKEND=backend:3003 diff --git a/cmd/main.go b/cmd/main.go index 5505cbe..3d2e271 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/isd-sgcu/rpkm67-gateway/config" + "github.com/isd-sgcu/rpkm67-gateway/constant" auth "github.com/isd-sgcu/rpkm67-gateway/internal/auth" "github.com/isd-sgcu/rpkm67-gateway/internal/router" "github.com/isd-sgcu/rpkm67-gateway/internal/user" @@ -42,7 +43,7 @@ func main() { userClient := userProto.NewUserServiceClient(authConn) userSvc := user.NewService(userClient, logger) - userHdr := user.NewHandler(userSvc, validate, logger) + userHdr := user.NewHandler(userSvc, conf.App.MaxFileSizeMb, constant.AllowedContentType, validate, logger) r := router.New(conf, corsHandler, authMiddleware) diff --git a/config/config.go b/config/config.go index e6f2ca3..fe0bce1 100644 --- a/config/config.go +++ b/config/config.go @@ -2,13 +2,15 @@ package config import ( "os" + "strconv" "github.com/joho/godotenv" ) type AppConfig struct { - Port string - Env string + Port string + Env string + MaxFileSizeMb int } type ServiceConfig struct { @@ -33,9 +35,15 @@ func LoadConfig() (*Config, error) { } } + maxFileSizeMb, err := strconv.ParseInt(os.Getenv("MAX_FILE_SIZE_MB"), 10, 64) + if err != nil { + return nil, err + } + appConfig := AppConfig{ - Port: os.Getenv("APP_PORT"), - Env: os.Getenv("APP_ENV"), + Port: os.Getenv("APP_PORT"), + Env: os.Getenv("APP_ENV"), + MaxFileSizeMb: int(maxFileSizeMb), } serviceConfig := ServiceConfig{ diff --git a/constant/user.constants.go b/constant/user.constants.go new file mode 100644 index 0000000..7a9fcd8 --- /dev/null +++ b/constant/user.constants.go @@ -0,0 +1,9 @@ +package constant + +var AllowedContentType = map[string]struct{}{ + "image/jpeg": {}, + "image/jpg": {}, + "image/png": {}, + "image/gif": {}, + "image/webp": {}, +} From 05d429d77b8f32253d8d9acceaa7c6b29ebb4963 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 00:38:30 +0700 Subject: [PATCH 08/12] user picture --- internal/dto/user.dto.go | 15 +++++-- internal/user/user.handler.go | 77 +++++++++++++++++++++++++---------- internal/user/user.service.go | 45 +++++++++++++++++--- 3 files changed, 108 insertions(+), 29 deletions(-) diff --git a/internal/dto/user.dto.go b/internal/dto/user.dto.go index e60d23f..59f858c 100644 --- a/internal/dto/user.dto.go +++ b/internal/dto/user.dto.go @@ -36,7 +36,7 @@ type FindOneUserResponse struct { User *User `json:"user"` } -type UpdateUserRequestBody struct { +type UpdateUserProfileBody struct { Nickname string `json:"nickname"` Title string `json:"title"` Firstname string `json:"firstname"` @@ -56,7 +56,7 @@ type UpdateUserRequestBody struct { GroupId string `json:"group_id"` } -type UpdateUserRequest struct { +type UpdateUserProfileRequest struct { Id string `json:"id" validate:"required"` Nickname string `json:"nickname"` Title string `json:"title"` @@ -77,6 +77,15 @@ type UpdateUserRequest struct { GroupId string `json:"group_id"` } -type UpdateUserResponse struct { +type UpdateUserProfileResponse struct { + User *User `json:"user"` +} + +type UpdateUserPictureRequest struct { + Id string `json:"id"` + File *DecomposedFile `json:"file"` +} + +type UpdateUserPictureResponse struct { User *User `json:"user"` } diff --git a/internal/user/user.handler.go b/internal/user/user.handler.go index 290dec1..646af58 100644 --- a/internal/user/user.handler.go +++ b/internal/user/user.handler.go @@ -12,21 +12,26 @@ import ( type Handler interface { FindOne(c router.Context) - Update(c router.Context) + UpdateProfile(c router.Context) + UpdatePicture(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 + maxFileSize int + allowedContentType map[string]struct{} + validate validator.DtoValidator + log *zap.Logger } -type handlerImpl struct { - svc Service - validate validator.DtoValidator - log *zap.Logger +func NewHandler(svc Service, maxFileSize int, allowedContentType map[string]struct{}, validate validator.DtoValidator, log *zap.Logger) Handler { + return &handlerImpl{ + svc: svc, + maxFileSize: maxFileSize, + allowedContentType: allowedContentType, + validate: validate, + log: log, + } } func (h *handlerImpl) FindOne(c router.Context) { @@ -51,41 +56,71 @@ func (h *handlerImpl) FindOne(c router.Context) { c.JSON(http.StatusOK, &dto.FindOneUserResponse{User: res.User}) } -func (h *handlerImpl) Update(c router.Context) { +func (h *handlerImpl) UpdateProfile(c router.Context) { id := c.Param("id") if id == "" { - h.log.Named("Update").Error("Param: id not found") + h.log.Named("UpdateProfile").Error("Param: id not found") c.BadRequestError("url parameter 'id' not found") return } - body := &dto.UpdateUserRequestBody{} + body := &dto.UpdateUserProfileBody{} if err := c.Bind(body); err != nil { - h.log.Named("Update").Error("Bind: failed to bind request body", zap.Error(err)) + h.log.Named("UpdateProfile").Error("Bind: failed to bind request body", zap.Error(err)) c.BadRequestError("Bind: failed to bind request body") return } if errorList := h.validate.Validate(body); errorList != nil { - h.log.Named("Update").Error("Validate: ", zap.Strings("errorList", errorList)) + h.log.Named("UpdateProfile").Error("Validate: ", zap.Strings("errorList", errorList)) c.BadRequestError(strings.Join(errorList, ", ")) return } req := h.createUpdateUserRequestDto(id, body) - res, appErr := h.svc.Update(req) + res, appErr := h.svc.UpdateProfile(req) + if appErr != nil { + h.log.Named("UpdateProfile").Error("Update: ", zap.Error(appErr)) + c.ResponseError(appErr) + return + } + + c.JSON(http.StatusOK, &dto.UpdateUserProfileResponse{User: res.User}) +} + +func (h *handlerImpl) UpdatePicture(c router.Context) { + id := c.Param("id") + if id == "" { + h.log.Named("UpdatePicture").Error("Param: id not found") + c.BadRequestError("url parameter 'id' not found") + return + } + + file, err := c.FormFile("picture", h.allowedContentType, int64(h.maxFileSize)) + if err != nil { + h.log.Named("UpdatePicture").Error("FormFile: failed to get file", zap.Error(err)) + c.BadRequestError(err.Error()) + return + } + + req := &dto.UpdateUserPictureRequest{ + Id: id, + File: file, + } + + res, appErr := h.svc.UpdatePicture(req) if appErr != nil { - h.log.Named("Update").Error("Update: ", zap.Error(appErr)) + h.log.Named("UpdatePicture").Error("UpdatePicture: ", zap.Error(appErr)) c.ResponseError(appErr) return } - c.JSON(http.StatusOK, &dto.UpdateUserResponse{User: res.User}) + c.JSON(http.StatusOK, &dto.UpdateUserPictureResponse{User: res.User}) } -func (h *handlerImpl) createUpdateUserRequestDto(id string, body *dto.UpdateUserRequestBody) *dto.UpdateUserRequest { - return &dto.UpdateUserRequest{ +func (h *handlerImpl) createUpdateUserRequestDto(id string, body *dto.UpdateUserProfileBody) *dto.UpdateUserProfileRequest { + return &dto.UpdateUserProfileRequest{ Id: id, Nickname: body.Nickname, Title: body.Title, diff --git a/internal/user/user.service.go b/internal/user/user.service.go index f2bd04b..9d93376 100644 --- a/internal/user/user.service.go +++ b/internal/user/user.service.go @@ -14,12 +14,14 @@ import ( type Service interface { FindOne(req *dto.FindOneUserRequest) (*dto.FindOneUserResponse, *apperror.AppError) - Update(req *dto.UpdateUserRequest) (*dto.UpdateUserResponse, *apperror.AppError) + UpdateProfile(req *dto.UpdateUserProfileRequest) (*dto.UpdateUserProfileResponse, *apperror.AppError) + UpdatePicture(req *dto.UpdateUserPictureRequest) (*dto.UpdateUserPictureResponse, *apperror.AppError) } type serviceImpl struct { client userProto.UserServiceClient - log *zap.Logger + //object svc + log *zap.Logger } func NewService(client userProto.UserServiceClient, log *zap.Logger) Service { @@ -57,7 +59,7 @@ func (s *serviceImpl) FindOne(req *dto.FindOneUserRequest) (*dto.FindOneUserResp }, nil } -func (s *serviceImpl) Update(req *dto.UpdateUserRequest) (*dto.UpdateUserResponse, *apperror.AppError) { +func (s *serviceImpl) UpdateProfile(req *dto.UpdateUserProfileRequest) (*dto.UpdateUserProfileResponse, *apperror.AppError) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -80,12 +82,45 @@ func (s *serviceImpl) Update(req *dto.UpdateUserRequest) (*dto.UpdateUserRespons } } - return &dto.UpdateUserResponse{ + return &dto.UpdateUserProfileResponse{ User: ProtoToDto(res.User), }, nil } -func (s *serviceImpl) createUpdateUserRequestProto(req *dto.UpdateUserRequest) *userProto.UpdateUserRequest { +func (s *serviceImpl) UpdatePicture(req *dto.UpdateUserPictureRequest) (*dto.UpdateUserPictureResponse, *apperror.AppError) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + //object code + + updateReq := &userProto.UpdateUserRequest{ + Id: req.Id, + // PhotoKey: req.PhotoKey, from object + } + + res, err := s.client.Update(ctx, updateReq) + if err != nil { + s.log.Named("UpdatePicture").Error("Update: ", zap.Error(err)) + st, ok := status.FromError(err) + if !ok { + return nil, apperror.InternalServer + } + switch st.Code() { + case codes.NotFound: + return nil, apperror.NotFoundError("User not found") + case codes.Internal: + return nil, apperror.InternalServerError(err.Error()) + default: + return nil, apperror.ServiceUnavailable + } + } + + return &dto.UpdateUserPictureResponse{ + User: ProtoToDto(res.User), + }, nil +} + +func (s *serviceImpl) createUpdateUserRequestProto(req *dto.UpdateUserProfileRequest) *userProto.UpdateUserRequest { return &userProto.UpdateUserRequest{ Id: req.Id, Nickname: req.Nickname, From 03b4a1a801ed4f0fb3369fd0f7d6d94c2b7cd4b5 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 11:28:37 +0700 Subject: [PATCH 09/12] feat: add latest tag --- .github/workflows/build-deploy.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml index 0987ec6..ac5db1e 100644 --- a/.github/workflows/build-deploy.yml +++ b/.github/workflows/build-deploy.yml @@ -11,6 +11,7 @@ on: env: IMAGE_NAME: ghcr.io/${{ github.repository }} + IMAGE_TAG: ${{ github.sha }} jobs: build: @@ -36,7 +37,7 @@ jobs: uses: docker/build-push-action@v3 with: push: true - tags: ${{ env.IMAGE_NAME }}:${{ github.ref_type == 'tag' && github.ref_name || github.sha }} + tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }},${{ env.IMAGE_NAME }}:latest cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:buildcache cache-to: type=registry,ref=${{ env.IMAGE_NAME }}:buildcache,mode=max From 67380ff1d2009219c5b3fe65c5baaee8899359d8 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 11:54:10 +0700 Subject: [PATCH 10/12] fix: qa --- docker-compose.qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.qa.yml b/docker-compose.qa.yml index 6a42fe5..557a43e 100644 --- a/docker-compose.qa.yml +++ b/docker-compose.qa.yml @@ -70,7 +70,7 @@ services: ACCESS_KEY: access_key SECRET_KEY: secret_key USE_SSL: true - BUCKET_NAME: rpkm67-qa + BUCKET_NAME: rpkm67-local networks: - rpkm67 ports: From 68344d7153ab708efac8a56a7e94a18ff2e528b7 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 12:36:16 +0700 Subject: [PATCH 11/12] compose --- .gitignore | 3 +- Makefile | 16 +++++ README.md | 48 +++++++++++++++ docker-compose.qa.yml | 108 ---------------------------------- internal/user/user.service.go | 2 +- 5 files changed, 67 insertions(+), 110 deletions(-) delete mode 100644 docker-compose.qa.yml diff --git a/.gitignore b/.gitignore index 6a4b79a..8ed44de 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ coverage.out coverage.html tmp -staff.json \ No newline at end of file +staff.json +docker-compose.qa.yml \ No newline at end of file diff --git a/Makefile b/Makefile index 5c28fca..3c593d5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,23 @@ +pull-latest-mac: + docker pull --platform linux/x86_64 ghcr.io/isd-sgcu/rpkm67-gateway:latest + docker pull --platform linux/x86_64 ghcr.io/isd-sgcu/rpkm67-auth:latest + docker pull --platform linux/x86_64 ghcr.io/isd-sgcu/rpkm67-backend:latest + docker pull --platform linux/x86_64 ghcr.io/isd-sgcu/rpkm67-checkin:latest + docker pull --platform linux/x86_64 ghcr.io/isd-sgcu/rpkm67-store:latest + +pull-latest-windows: + docker pull ghcr.io/isd-sgcu/rpkm67-gateway:latest + docker pull ghcr.io/isd-sgcu/rpkm67-auth:latest + docker pull ghcr.io/isd-sgcu/rpkm67-backend:latest + docker pull ghcr.io/isd-sgcu/rpkm67-checkin:latest + docker pull ghcr.io/isd-sgcu/rpkm67-store:latest + docker: + docker rm -v -f $$(docker ps -qa) docker-compose up docker-qa: + docker rm -v -f $$(docker ps -qa) docker-compose -f docker-compose.qa.yml up server: diff --git a/README.md b/README.md index c682c22..c7c7f72 100644 --- a/README.md +++ b/README.md @@ -1 +1,49 @@ # rpkm67-gateway + +## Stack + +- golang +- gRPC +- postgresql +- redis +- minio + +## Getting Started + +### Prerequisites + +- 💻 +- golang 1.22 or [later](https://go.dev) +- docker +- makefile +- [Go Air](https://github.com/air-verse/air) + +### Installation + +1. Clone this repo +2. Run `go mod download` to download all the dependencies. + +### Running only this service +1. Copy `.env.template` and paste it in the same directory as `.env`. Fill in the appropriate values. +2. Run `make docker`. +3. Run `make server` or `air` for hot-reload. + +### Running all RPKM67 services (all other services are run as containers) +1. Copy `docker-compose.qa.template.yml` and paste it in the same directory as `docker-compose.qa.yml`. Fill in the appropriate values. +2. Run `make pull-latest-mac` or `make pull-latest-windows` to pull the latest images of other services. +1. Run `make docker-qa`. +2. Run `make server` or `air` for hot-reload. + +### Unit Testing +1. Run `make test` + +## Other microservices/repositories of RPKM67 +- [gateway](https://github.com/isd-sgcu/rpkm67-gateway): Routing and request handling +- [auth](https://github.com/isd-sgcu/rpkm67-auth): Authentication and user service +- [backend](https://github.com/isd-sgcu/rpkm67-backend): Group, Baan selection and Stamp, Pin business logic +- [checkin](https://github.com/isd-sgcu/rpkm67-checkin): Checkin for events service +- [store](https://github.com/isd-sgcu/rpkm67-store): Object storage service for user profile pictures +- [model](https://github.com/isd-sgcu/rpkm67-model): SQL table schema and models +- [proto](https://github.com/isd-sgcu/rpkm67-proto): Protobuf files generator +- [go-proto](https://github.com/isd-sgcu/rpkm67-go-proto): Generated protobuf files for golang +- [frontend](https://github.com/isd-sgcu/firstdate-rpkm67-frontend): Frontend web application diff --git a/docker-compose.qa.yml b/docker-compose.qa.yml deleted file mode 100644 index 557a43e..0000000 --- a/docker-compose.qa.yml +++ /dev/null @@ -1,108 +0,0 @@ -version: "3.9" - -services: - auth: - image: ghcr.io/isd-sgcu/rpkm67-auth:914e1c9a6b3a8d2ac1b0a9ff4173076fc36d1df3 - container_name: auth - restart: unless-stopped - environment: - APP_PORT: 3002 - APP_ENV: development - DB_URL: postgres://root:1234@db:5432/rpkm67_db - REDIS_HOST: localhost - REDIS_PORT: 6379 - REDIS_PASSWORD: 5678 - JWT_SECRET: secret - JWT_ACCESS_TTL: 3600 - JWT_REFRESH_TTL: 259200 - JWT_ISSUER: issuer - JWT_RESET_TOKEN_TTL: 900 - OAUTH_CLIENT_ID: client_id - OAUTH_CLIENT_SECRET: client_secret - OAUTH_REDIRECT_URI: http://localhost:3000/auth/google/callback - networks: - - rpkm67 - ports: - - "3002:3002" - - backend: - image: ghcr.io/isd-sgcu/rpkm67-backend:40ca3d5cda65663fcc8c32ede5170a2dc456d7b9 - container_name: backend - restart: unless-stopped - environment: - APP_PORT: 3003 - APP_ENV: development - DB_URL: postgres://root:1234@db:5432/rpkm67_db - REDIS_HOST: cache - REDIS_PORT: 6379 - REDIS_PASSWORD: 5678 - PIN_WORKSHOP_CODE: workshop - PIN_WORKSHOP_COUNT: 5 - PIN_LANDMARK_CODE: landmark - PIN_LANDMARK_COUNT: 4 - networks: - - rpkm67 - ports: - - "3003:3003" - - checkin: - image: ghcr.io/isd-sgcu/rpkm67-checkin:718156635121b4d560c5d4d4f75fd9abdf3103cb - container_name: checkin - restart: unless-stopped - environment: - APP_PORT: 3004 - APP_ENV: development - DB_URL: postgres://root:1234@db:5432/rpkm67_db - networks: - - rpkm67 - ports: - - "3004:3004" - - store: - image: ghcr.io/isd-sgcu/rpkm67-store:a6f718f5556abfb44b10b178fba0db9f9dc717a1 - container_name: store - restart: unless-stopped - environment: - APP_PORT: 3005 - APP_ENV: development - APP_MAX_FILE_SIZE_MB: 20 - ENDPOINT: endpoint - ACCESS_KEY: access_key - SECRET_KEY: secret_key - USE_SSL: true - BUCKET_NAME: rpkm67-local - networks: - - rpkm67 - ports: - - "3005:3005" - - db: - image: postgres:15.1-alpine3.17 - container_name: db - restart: unless-stopped - environment: - POSTGRES_USER: root - POSTGRES_PASSWORD: "1234" - POSTGRES_DB: rpkm67_db - networks: - - rpkm67 - volumes: - - ./volumes/postgres:/var/lib/postgresql/data - ports: - - "5432:5432" - - cache: - image: redis:7.2.3-alpine - container_name: cache - restart: unless-stopped - environment: - REDIS_HOST: localhost - REDIS_PASSWORD: "5678" - networks: - - rpkm67 - ports: - - "6379:6379" - -networks: - rpkm67: - name: rpkm67 diff --git a/internal/user/user.service.go b/internal/user/user.service.go index 9d93376..420cbe1 100644 --- a/internal/user/user.service.go +++ b/internal/user/user.service.go @@ -20,7 +20,7 @@ type Service interface { type serviceImpl struct { client userProto.UserServiceClient - //object svc + // object svc log *zap.Logger } From 5e16bc6bb5b53c6b1b3b331973b27067c762e713 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sat, 29 Jun 2024 12:37:51 +0700 Subject: [PATCH 12/12] feat: qa --- docker-compose.qa.template.yml | 123 +++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docker-compose.qa.template.yml diff --git a/docker-compose.qa.template.yml b/docker-compose.qa.template.yml new file mode 100644 index 0000000..603d04a --- /dev/null +++ b/docker-compose.qa.template.yml @@ -0,0 +1,123 @@ +version: "3.9" + +services: + # gateway: + # image: ghcr.io/isd-sgcu/rpkm67-gateway:latest + # container_name: gateway + # restart: unless-stopped + # environment: + # APP_PORT: 3001 + # APP_ENV: development + # APP_MAX_FILE_SIZE_MB: 10 + # CORS_ORIGINS: http://localhost:3000 + # SERVICE_AUTH: http://localhost:3002 + # SERVICE_BACKEND: backend:3003 + # SERVICE_CHECKIN: checkin:3004 + # SERVICE_STORE: store:3005 + # networks: + # - rpkm67 + # ports: + # - "3001:3001" + + auth: + image: ghcr.io/isd-sgcu/rpkm67-auth:latest + container_name: auth + restart: unless-stopped + environment: + APP_PORT: 3002 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + REDIS_HOST: localhost + REDIS_PORT: 6379 + REDIS_PASSWORD: 5678 + JWT_SECRET: secret + JWT_ACCESS_TTL: 3600 + JWT_REFRESH_TTL: 259200 + JWT_ISSUER: rpkm67.sgcu.in.th + JWT_RESET_TOKEN_TTL: 900 + networks: + - rpkm67 + ports: + - "3002:3002" + + backend: + image: ghcr.io/isd-sgcu/rpkm67-backend:latest + container_name: backend + restart: unless-stopped + environment: + APP_PORT: 3003 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + REDIS_HOST: cache + REDIS_PORT: 6379 + REDIS_PASSWORD: 5678 + PIN_WORKSHOP_CODE: workshop + PIN_WORKSHOP_COUNT: 5 + PIN_LANDMARK_CODE: landmark + PIN_LANDMARK_COUNT: 4 + networks: + - rpkm67 + ports: + - "3003:3003" + + checkin: + image: ghcr.io/isd-sgcu/rpkm67-checkin:latest + container_name: checkin + restart: unless-stopped + environment: + APP_PORT: 3004 + APP_ENV: development + DB_URL: postgres://root:1234@db:5432/rpkm67_db + networks: + - rpkm67 + ports: + - "3004:3004" + + store: + image: ghcr.io/isd-sgcu/rpkm67-store:latest + container_name: store + restart: unless-stopped + environment: + APP_PORT: 3005 + APP_ENV: development + APP_MAX_FILE_SIZE_MB: 20 + STORE_ENDPOINT: endpoint + STORE_ACCESS_KEY: access_key + STORE_SECRET_KEY: secret_key + STORE_USE_SSL: true + STORE_BUCKET_NAME: rpkm67-local + networks: + - rpkm67 + ports: + - "3005:3005" + + db: + image: postgres:15.1-alpine3.17 + container_name: db + restart: unless-stopped + environment: + POSTGRES_USER: root + POSTGRES_PASSWORD: "1234" + POSTGRES_DB: rpkm67_db + networks: + - rpkm67 + volumes: + - ./volumes/postgres:/var/lib/postgresql/data + ports: + - "5432:5432" + + cache: + image: redis:7.2.3-alpine + container_name: cache + restart: unless-stopped + environment: + REDIS_HOST: localhost + REDIS_PASSWORD: "5678" + networks: + - rpkm67 + ports: + - "6379:6379" + +networks: + rpkm67: + name: rpkm67