RyZ commited on
Commit
3b2d340
·
1 Parent(s): d236183

feature: Adding Login by Google logic

Browse files
controllers/auth_controller.go CHANGED
@@ -17,6 +17,7 @@ type AuthController interface {
17
  LoginUser(ctx *gin.Context)
18
  LoginAdmin(ctx *gin.Context)
19
  LoginWorker(ctx *gin.Context)
 
20
  GetProfile(ctx *gin.Context)
21
  GetAllUsers(ctx *gin.Context)
22
  GetAllWorkers(ctx *gin.Context)
@@ -214,3 +215,28 @@ func (c *authController) GetAllWorkers(ctx *gin.Context) {
214
 
215
  utils.SendSuccessResponse(ctx, "Workers retrieved", workers)
216
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  LoginUser(ctx *gin.Context)
18
  LoginAdmin(ctx *gin.Context)
19
  LoginWorker(ctx *gin.Context)
20
+ GoogleAuth(ctx *gin.Context)
21
  GetProfile(ctx *gin.Context)
22
  GetAllUsers(ctx *gin.Context)
23
  GetAllWorkers(ctx *gin.Context)
 
215
 
216
  utils.SendSuccessResponse(ctx, "Workers retrieved", workers)
217
  }
218
+
219
+ // @Summary Google Authentication
220
+ // @Description Authenticate with Google ID token and get JWT
221
+ // @Tags Auth
222
+ // @Accept json
223
+ // @Produce json
224
+ // @Param request body dto.GoogleAuthRequest true "Google Auth Request"
225
+ // @Success 200 {object} dto.GoogleAuthResponse
226
+ // @Failure 401 {object} map[string]string
227
+ // @Router /api/auth/google [post]
228
+ func (c *authController) GoogleAuth(ctx *gin.Context) {
229
+ var req dto.GoogleAuthRequest
230
+ if err := ctx.ShouldBindJSON(&req); err != nil {
231
+ utils.SendErrorResponse(ctx, http.StatusBadRequest, err.Error())
232
+ return
233
+ }
234
+
235
+ response, err := c.authService.GoogleAuth(req)
236
+ if err != nil {
237
+ utils.SendErrorResponse(ctx, http.StatusUnauthorized, err.Error())
238
+ return
239
+ }
240
+
241
+ utils.SendSuccessResponse(ctx, "Authentication successful", response)
242
+ }
controllers/report_controller.go CHANGED
@@ -34,7 +34,7 @@ func NewReportController(reportService services.ReportService) ReportController
34
  // @Security BearerAuth
35
  // @Success 200 {object} dto.ReportResponse
36
  // @Failure 400 {object} map[string]string
37
- // @Router /api/report [post]
38
  func (c *reportController) CreateReport(ctx *gin.Context) {
39
  userIDVal, exists := ctx.Get("user_id")
40
  if !exists {
 
34
  // @Security BearerAuth
35
  // @Success 200 {object} dto.ReportResponse
36
  // @Failure 400 {object} map[string]string
37
+ // @Router /api/user/report [post]
38
  func (c *reportController) CreateReport(ctx *gin.Context) {
39
  userIDVal, exists := ctx.Get("user_id")
40
  if !exists {
models/dto/google_auth_dto.go ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package dto
2
+
3
+ type GoogleAuthRequest struct {
4
+ IDToken string `json:"idToken" binding:"required"`
5
+ }
6
+
7
+ type GoogleAuthResponse struct {
8
+ Token string `json:"token"`
9
+ User GoogleUserDetails `json:"user"`
10
+ }
11
+
12
+ type GoogleUserDetails struct {
13
+ Email string `json:"email"`
14
+ Fullname string `json:"fullname"`
15
+ IsNewUser bool `json:"isNewUser"`
16
+ }
provider/controller_provider.go CHANGED
@@ -3,32 +3,24 @@ package provider
3
  import "dinacom-11.0-backend/controllers"
4
 
5
  type ControllerProvider interface {
6
- ProvideConnectionController() controllers.ConnectionController
7
  ProvideAuthController() controllers.AuthController
8
  ProvideReportController() controllers.ReportController
9
  }
10
 
11
  type controllerProvider struct {
12
- connectionController controllers.ConnectionController
13
- authController controllers.AuthController
14
- reportController controllers.ReportController
15
  }
16
 
17
  func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {
18
- connectionController := controllers.NewConnectionController(servicesProvider.ProvideConnectionService())
19
  authController := controllers.NewAuthController(servicesProvider.ProvideAuthService())
20
  reportController := controllers.NewReportController(servicesProvider.ProvideReportService())
21
  return &controllerProvider{
22
- connectionController: connectionController,
23
- authController: authController,
24
- reportController: reportController,
25
  }
26
  }
27
 
28
- func (c *controllerProvider) ProvideConnectionController() controllers.ConnectionController {
29
- return c.connectionController
30
- }
31
-
32
  func (c *controllerProvider) ProvideAuthController() controllers.AuthController {
33
  return c.authController
34
  }
 
3
  import "dinacom-11.0-backend/controllers"
4
 
5
  type ControllerProvider interface {
 
6
  ProvideAuthController() controllers.AuthController
7
  ProvideReportController() controllers.ReportController
8
  }
9
 
10
  type controllerProvider struct {
11
+ authController controllers.AuthController
12
+ reportController controllers.ReportController
 
13
  }
14
 
15
  func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {
 
16
  authController := controllers.NewAuthController(servicesProvider.ProvideAuthService())
17
  reportController := controllers.NewReportController(servicesProvider.ProvideReportService())
18
  return &controllerProvider{
19
+ authController: authController,
20
+ reportController: reportController,
 
21
  }
22
  }
23
 
 
 
 
 
24
  func (c *controllerProvider) ProvideAuthController() controllers.AuthController {
25
  return c.authController
26
  }
provider/repositories_provider.go CHANGED
@@ -3,32 +3,24 @@ package provider
3
  import "dinacom-11.0-backend/repositories"
4
 
5
  type RepositoriesProvider interface {
6
- ProvideConnectionRepository() repositories.ConnectionRepository
7
  ProvideUserRepository() repositories.UserRepository
8
  ProvideReportRepository() repositories.ReportRepository
9
  }
10
 
11
  type repositoriesProvider struct {
12
- connectionRepository repositories.ConnectionRepository
13
- userRepository repositories.UserRepository
14
- reportRepository repositories.ReportRepository
15
  }
16
 
17
  func NewRepositoriesProvider(cfg ConfigProvider) RepositoriesProvider {
18
- connectionRepository := repositories.NewConnectionRepository(cfg.ProvideDatabaseConfig().GetInstance())
19
  userRepository := repositories.NewUserRepository(cfg.ProvideDatabaseConfig().GetInstance())
20
  reportRepository := repositories.NewReportRepository(cfg.ProvideDatabaseConfig().GetInstance())
21
  return &repositoriesProvider{
22
- connectionRepository: connectionRepository,
23
- userRepository: userRepository,
24
- reportRepository: reportRepository,
25
  }
26
  }
27
 
28
- func (rp *repositoriesProvider) ProvideConnectionRepository() repositories.ConnectionRepository {
29
- return rp.connectionRepository
30
- }
31
-
32
  func (rp *repositoriesProvider) ProvideUserRepository() repositories.UserRepository {
33
  return rp.userRepository
34
  }
 
3
  import "dinacom-11.0-backend/repositories"
4
 
5
  type RepositoriesProvider interface {
 
6
  ProvideUserRepository() repositories.UserRepository
7
  ProvideReportRepository() repositories.ReportRepository
8
  }
9
 
10
  type repositoriesProvider struct {
11
+ userRepository repositories.UserRepository
12
+ reportRepository repositories.ReportRepository
 
13
  }
14
 
15
  func NewRepositoriesProvider(cfg ConfigProvider) RepositoriesProvider {
 
16
  userRepository := repositories.NewUserRepository(cfg.ProvideDatabaseConfig().GetInstance())
17
  reportRepository := repositories.NewReportRepository(cfg.ProvideDatabaseConfig().GetInstance())
18
  return &repositoriesProvider{
19
+ userRepository: userRepository,
20
+ reportRepository: reportRepository,
 
21
  }
22
  }
23
 
 
 
 
 
24
  func (rp *repositoriesProvider) ProvideUserRepository() repositories.UserRepository {
25
  return rp.userRepository
26
  }
provider/services_provider.go CHANGED
@@ -3,32 +3,24 @@ package provider
3
  import "dinacom-11.0-backend/services"
4
 
5
  type ServicesProvider interface {
6
- ProvideConnectionService() services.ConnectionService
7
  ProvideAuthService() services.AuthService
8
  ProvideReportService() services.ReportService
9
  }
10
 
11
  type servicesProvider struct {
12
- connectionService services.ConnectionService
13
- authService services.AuthService
14
- reportService services.ReportService
15
  }
16
 
17
  func NewServicesProvider(repoProvider RepositoriesProvider, configProvider ConfigProvider) ServicesProvider {
18
- connectionService := services.NewConnectionService(repoProvider.ProvideConnectionRepository())
19
  authService := services.NewAuthService(repoProvider.ProvideUserRepository())
20
  reportService := services.NewReportService(repoProvider.ProvideReportRepository())
21
  return &servicesProvider{
22
- connectionService: connectionService,
23
- authService: authService,
24
- reportService: reportService,
25
  }
26
  }
27
 
28
- func (s *servicesProvider) ProvideConnectionService() services.ConnectionService {
29
- return s.connectionService
30
- }
31
-
32
  func (s *servicesProvider) ProvideAuthService() services.AuthService {
33
  return s.authService
34
  }
 
3
  import "dinacom-11.0-backend/services"
4
 
5
  type ServicesProvider interface {
 
6
  ProvideAuthService() services.AuthService
7
  ProvideReportService() services.ReportService
8
  }
9
 
10
  type servicesProvider struct {
11
+ authService services.AuthService
12
+ reportService services.ReportService
 
13
  }
14
 
15
  func NewServicesProvider(repoProvider RepositoriesProvider, configProvider ConfigProvider) ServicesProvider {
 
16
  authService := services.NewAuthService(repoProvider.ProvideUserRepository())
17
  reportService := services.NewReportService(repoProvider.ProvideReportRepository())
18
  return &servicesProvider{
19
+ authService: authService,
20
+ reportService: reportService,
 
21
  }
22
  }
23
 
 
 
 
 
24
  func (s *servicesProvider) ProvideAuthService() services.AuthService {
25
  return s.authService
26
  }
router/auth_router.go CHANGED
@@ -29,6 +29,8 @@ func (r *authRouter) Setup(router *gin.RouterGroup) {
29
  userGroup.POST("/verify-otp", r.authController.VerifyOTP)
30
  userGroup.POST("/login", r.authController.LoginUser)
31
 
 
 
32
  adminGroup := authGroup.Group("/admin")
33
  adminGroup.POST("/login", r.authController.LoginAdmin)
34
 
 
29
  userGroup.POST("/verify-otp", r.authController.VerifyOTP)
30
  userGroup.POST("/login", r.authController.LoginUser)
31
 
32
+ authGroup.POST("/google", r.authController.GoogleAuth)
33
+
34
  adminGroup := authGroup.Group("/admin")
35
  adminGroup.POST("/login", r.authController.LoginAdmin)
36
 
router/connection_router.go DELETED
@@ -1,17 +0,0 @@
1
- package router
2
-
3
- import (
4
- "dinacom-11.0-backend/provider"
5
- "github.com/gin-contrib/gzip"
6
- "github.com/gin-gonic/gin"
7
- )
8
-
9
- func ConnectionRouter(router *gin.Engine, controller provider.ControllerProvider) {
10
- connectionController := controller.ProvideConnectionController()
11
- routerGroup := router.Group("/api")
12
- routerGroup.Use(gzip.Gzip(gzip.DefaultCompression))
13
- {
14
- routerGroup.POST("/connect", connectionController.Connect)
15
- }
16
-
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
router/report_router.go CHANGED
@@ -20,7 +20,7 @@ func NewReportRouter(reportController controllers.ReportController) ReportRouter
20
  }
21
 
22
  func (r *reportRouter) Setup(router *gin.RouterGroup) {
23
- reportGroup := router.Group("/report")
24
  reportGroup.Use(middleware.AuthMiddleware())
25
  reportGroup.POST("", r.reportController.CreateReport)
26
  }
 
20
  }
21
 
22
  func (r *reportRouter) Setup(router *gin.RouterGroup) {
23
+ reportGroup := router.Group("/user/report")
24
  reportGroup.Use(middleware.AuthMiddleware())
25
  reportGroup.POST("", r.reportController.CreateReport)
26
  }
router/router.go CHANGED
@@ -3,13 +3,13 @@ package router
3
  import (
4
  _ "dinacom-11.0-backend/docs"
5
  "dinacom-11.0-backend/provider"
 
6
  swaggerFiles "github.com/swaggo/files"
7
  ginSwagger "github.com/swaggo/gin-swagger"
8
  )
9
 
10
  func RunRouter(appProvider provider.AppProvider) {
11
  router, controller, config := appProvider.ProvideRouter(), appProvider.ProvideControllers(), appProvider.ProvideConfig()
12
- ConnectionRouter(router, controller)
13
 
14
  authRouter := NewAuthRouter(controller.ProvideAuthController())
15
  authRouter.Setup(router.Group("/api"))
 
3
  import (
4
  _ "dinacom-11.0-backend/docs"
5
  "dinacom-11.0-backend/provider"
6
+
7
  swaggerFiles "github.com/swaggo/files"
8
  ginSwagger "github.com/swaggo/gin-swagger"
9
  )
10
 
11
  func RunRouter(appProvider provider.AppProvider) {
12
  router, controller, config := appProvider.ProvideRouter(), appProvider.ProvideControllers(), appProvider.ProvideConfig()
 
13
 
14
  authRouter := NewAuthRouter(controller.ProvideAuthController())
15
  authRouter.Setup(router.Group("/api"))
services/auth_service.go CHANGED
@@ -18,6 +18,7 @@ type AuthService interface {
18
  LoginUser(req dto.LoginRequest) (string, error)
19
  LoginAdmin(req dto.LoginRequest) (string, error)
20
  LoginWorker(req dto.LoginRequest) (string, error)
 
21
  GetProfile(userID uuid.UUID) (*dto.UserResponse, error)
22
  GetAllUsers() ([]dto.UserResponse, error)
23
  GetAllWorkers() ([]dto.UserResponse, error)
@@ -221,3 +222,43 @@ func (s *authService) GetAllWorkers() ([]dto.UserResponse, error) {
221
  }
222
  return response, nil
223
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  LoginUser(req dto.LoginRequest) (string, error)
19
  LoginAdmin(req dto.LoginRequest) (string, error)
20
  LoginWorker(req dto.LoginRequest) (string, error)
21
+ GoogleAuth(req dto.GoogleAuthRequest) (*dto.GoogleAuthResponse, error)
22
  GetProfile(userID uuid.UUID) (*dto.UserResponse, error)
23
  GetAllUsers() ([]dto.UserResponse, error)
24
  GetAllWorkers() ([]dto.UserResponse, error)
 
222
  }
223
  return response, nil
224
  }
225
+
226
+ func (s *authService) GoogleAuth(req dto.GoogleAuthRequest) (*dto.GoogleAuthResponse, error) {
227
+ tokenInfo, err := utils.VerifyGoogleToken(req.IDToken)
228
+ if err != nil {
229
+ return nil, errors.New("invalid Google token")
230
+ }
231
+
232
+ existingUser, _ := s.userRepo.FindUserByEmail(tokenInfo.Email)
233
+ isNewUser := false
234
+
235
+ if existingUser == nil {
236
+ isNewUser = true
237
+ newUser := &entity.User{
238
+ Username: tokenInfo.Email,
239
+ Fullname: tokenInfo.Name,
240
+ Email: tokenInfo.Email,
241
+ Role: "user",
242
+ Password: "",
243
+ Verified: true,
244
+ }
245
+ if err := s.userRepo.CreateUser(newUser); err != nil {
246
+ return nil, err
247
+ }
248
+ existingUser, _ = s.userRepo.FindUserByEmail(tokenInfo.Email)
249
+ }
250
+
251
+ token, err := utils.GenerateAccessToken(existingUser.ID, existingUser.Role, existingUser.Email)
252
+ if err != nil {
253
+ return nil, err
254
+ }
255
+
256
+ return &dto.GoogleAuthResponse{
257
+ Token: token,
258
+ User: dto.GoogleUserDetails{
259
+ Email: existingUser.Email,
260
+ Fullname: existingUser.Fullname,
261
+ IsNewUser: isNewUser,
262
+ },
263
+ }, nil
264
+ }
utils/google_auth_util.go ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package utils
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "io"
7
+ "net/http"
8
+ )
9
+
10
+ type GoogleTokenInfo struct {
11
+ Email string `json:"email"`
12
+ EmailVerified string `json:"email_verified"`
13
+ Name string `json:"name"`
14
+ Picture string `json:"picture"`
15
+ Sub string `json:"sub"`
16
+ }
17
+
18
+ func VerifyGoogleToken(idToken string) (*GoogleTokenInfo, error) {
19
+ resp, err := http.Get(fmt.Sprintf("https://oauth2.googleapis.com/tokeninfo?id_token=%s", idToken))
20
+ if err != nil {
21
+ return nil, err
22
+ }
23
+ defer resp.Body.Close()
24
+
25
+ if resp.StatusCode != http.StatusOK {
26
+ return nil, fmt.Errorf("invalid token")
27
+ }
28
+
29
+ body, err := io.ReadAll(resp.Body)
30
+ if err != nil {
31
+ return nil, err
32
+ }
33
+
34
+ var tokenInfo GoogleTokenInfo
35
+ if err := json.Unmarshal(body, &tokenInfo); err != nil {
36
+ return nil, err
37
+ }
38
+
39
+ return &tokenInfo, nil
40
+ }