Spaces:
Configuration error
Configuration error
Commit ·
897bab5
1
Parent(s): ad00352
Deploy files from GitHub repository
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- controller/controller.go +1 -1
- space/Dockerfile +3 -0
- space/services/region_service.go +10 -8
- space/space/services/region_service.go +8 -10
- space/space/space/README.md +5 -1
- space/space/space/space/controller/user/user_profile_controller.go +1 -1
- space/space/space/space/controller/user/user_update_profile_controller.go +2 -4
- space/space/space/space/logs/error_log.txt +1 -0
- space/space/space/space/middleware/authentication_middleware.go +0 -3
- space/space/space/space/models/response_model.go +5 -0
- space/space/space/space/repositories/account_repository.go +0 -4
- space/space/space/space/repositories/forgot_password_repository.go +22 -0
- space/space/space/space/router/router.go +8 -1
- space/space/space/space/services/external_authentication_service.go +4 -5
- space/space/space/space/services/user_profile_service.go +50 -6
- space/space/space/space/space/.gitignore +4 -2
- space/space/space/space/space/config/config.go +10 -0
- space/space/space/space/space/config/database_connection_config.go +4 -0
- space/space/space/space/space/controller/auth/auth_external_controller.go +20 -0
- space/space/space/space/space/controller/auth/auth_forgot_password_controller.go +1 -0
- space/space/space/space/space/controller/email/email_create_verification_controller.go +21 -0
- space/space/space/space/space/controller/email/email_validate_controller.go +24 -0
- space/space/space/space/space/controller/options/option_category_controller.go +19 -0
- space/space/space/space/space/controller/options/option_value_controller.go +19 -0
- space/space/space/space/space/controller/region/city/city_list_controller.go +21 -0
- space/space/space/space/space/controller/region/city/city_seeds_controller.go +17 -0
- space/space/space/space/space/controller/region/province/province_list_controller.go +17 -0
- space/space/space/space/space/controller/region/province/province_seeds_controller.go +17 -0
- space/space/space/space/space/go.mod +23 -2
- space/space/space/space/space/go.sum +46 -0
- space/space/space/space/space/logs/error_log.txt +0 -9
- space/space/space/space/space/middleware/authentication_middleware.go +3 -3
- space/space/space/space/space/models/database_orm_model.go +33 -5
- space/space/space/space/space/models/request_model.go +17 -4
- space/space/space/space/space/models/response_model.go +7 -0
- space/space/space/space/space/repositories/account_repository.go +0 -1
- space/space/space/space/space/repositories/email_verification_repository.go +15 -1
- space/space/space/space/space/repositories/external_auth_repository.go +37 -0
- space/space/space/space/space/repositories/option_repository.go +43 -0
- space/space/space/space/space/repositories/region_repository.go +47 -0
- space/space/space/space/space/router/auth_route.go +1 -0
- space/space/space/space/space/router/email_route.go +3 -3
- space/space/space/space/space/router/options_route.go +20 -0
- space/space/space/space/space/router/router.go +1 -0
- space/space/space/space/space/services/authentication_service.go +1 -4
- space/space/space/space/space/services/email_verification_service.go +36 -1
- space/space/space/space/space/services/external_authentication_service.go +55 -0
- space/space/space/space/space/services/option_service.go +70 -0
- space/space/space/space/space/services/region_service.go +90 -0
- space/space/space/space/space/space/controller/email/email_create_verification.go +6 -7
controller/controller.go
CHANGED
|
@@ -46,11 +46,11 @@ func (controller *Controller[T1, T2, T3]) RequestJSON(c *gin.Context, act func()
|
|
| 46 |
func (controller *Controller[T1, T2, T3]) Response(c *gin.Context) {
|
| 47 |
switch {
|
| 48 |
case controller.Service.Error != nil:
|
|
|
|
| 49 |
utils.ResponseFAIL(c, 500, models.Exception{
|
| 50 |
InternalServerError: true,
|
| 51 |
Message: "Internal Server Error",
|
| 52 |
})
|
| 53 |
-
utils.LogError(controller.Service.Error)
|
| 54 |
case controller.Service.Exception.DataDuplicate:
|
| 55 |
utils.ResponseFAIL(c, 400, controller.Service.Exception)
|
| 56 |
case controller.Service.Exception.Unauthorized:
|
|
|
|
| 46 |
func (controller *Controller[T1, T2, T3]) Response(c *gin.Context) {
|
| 47 |
switch {
|
| 48 |
case controller.Service.Error != nil:
|
| 49 |
+
utils.LogError(controller.Service.Error)
|
| 50 |
utils.ResponseFAIL(c, 500, models.Exception{
|
| 51 |
InternalServerError: true,
|
| 52 |
Message: "Internal Server Error",
|
| 53 |
})
|
|
|
|
| 54 |
case controller.Service.Exception.DataDuplicate:
|
| 55 |
utils.ResponseFAIL(c, 400, controller.Service.Exception)
|
| 56 |
case controller.Service.Exception.Unauthorized:
|
space/Dockerfile
CHANGED
|
@@ -28,6 +28,9 @@ WORKDIR /app
|
|
| 28 |
# Copy hasil build dari builder ke image runtime
|
| 29 |
COPY --from=builder /app/main .
|
| 30 |
|
|
|
|
|
|
|
|
|
|
| 31 |
# Copy file .env untuk konfigurasi environment
|
| 32 |
COPY .env .env
|
| 33 |
|
|
|
|
| 28 |
# Copy hasil build dari builder ke image runtime
|
| 29 |
COPY --from=builder /app/main .
|
| 30 |
|
| 31 |
+
# Copy folder utils (termasuk file seeder) dari builder ke runtime
|
| 32 |
+
COPY --from=builder /app/utils ./utils
|
| 33 |
+
|
| 34 |
# Copy file .env untuk konfigurasi environment
|
| 35 |
COPY .env .env
|
| 36 |
|
space/services/region_service.go
CHANGED
|
@@ -4,6 +4,8 @@ import (
|
|
| 4 |
"encoding/json"
|
| 5 |
"log"
|
| 6 |
"os"
|
|
|
|
|
|
|
| 7 |
|
| 8 |
"api.qobiltu.id/models"
|
| 9 |
"api.qobiltu.id/repositories"
|
|
@@ -18,10 +20,10 @@ type CityService struct {
|
|
| 18 |
}
|
| 19 |
|
| 20 |
func seedCity() ([]models.RegionCity, error) {
|
| 21 |
-
log.Println("Seed City
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
file, err := os.Open(
|
| 25 |
if err != nil {
|
| 26 |
return nil, err
|
| 27 |
}
|
|
@@ -34,10 +36,10 @@ func seedCity() ([]models.RegionCity, error) {
|
|
| 34 |
}
|
| 35 |
|
| 36 |
func seedProvince() ([]models.RegionProvince, error) {
|
| 37 |
-
log.Println("Seed
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
file, err := os.Open(
|
| 41 |
if err != nil {
|
| 42 |
return nil, err
|
| 43 |
}
|
|
|
|
| 4 |
"encoding/json"
|
| 5 |
"log"
|
| 6 |
"os"
|
| 7 |
+
"path/filepath"
|
| 8 |
+
"runtime"
|
| 9 |
|
| 10 |
"api.qobiltu.id/models"
|
| 11 |
"api.qobiltu.id/repositories"
|
|
|
|
| 20 |
}
|
| 21 |
|
| 22 |
func seedCity() ([]models.RegionCity, error) {
|
| 23 |
+
log.Println("Seed City")
|
| 24 |
+
_, b, _, _ := runtime.Caller(0)
|
| 25 |
+
basePath := filepath.Dir(b)
|
| 26 |
+
file, err := os.Open(filepath.Join(basePath, "..", "utils", "seeds", "city.json"))
|
| 27 |
if err != nil {
|
| 28 |
return nil, err
|
| 29 |
}
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
func seedProvince() ([]models.RegionProvince, error) {
|
| 39 |
+
log.Println("Seed City")
|
| 40 |
+
_, b, _, _ := runtime.Caller(0)
|
| 41 |
+
basePath := filepath.Dir(b)
|
| 42 |
+
file, err := os.Open(filepath.Join(basePath, "..", "utils", "seeds", "province.json"))
|
| 43 |
if err != nil {
|
| 44 |
return nil, err
|
| 45 |
}
|
space/space/services/region_service.go
CHANGED
|
@@ -4,8 +4,6 @@ import (
|
|
| 4 |
"encoding/json"
|
| 5 |
"log"
|
| 6 |
"os"
|
| 7 |
-
"path/filepath"
|
| 8 |
-
"runtime"
|
| 9 |
|
| 10 |
"api.qobiltu.id/models"
|
| 11 |
"api.qobiltu.id/repositories"
|
|
@@ -20,10 +18,10 @@ type CityService struct {
|
|
| 20 |
}
|
| 21 |
|
| 22 |
func seedCity() ([]models.RegionCity, error) {
|
| 23 |
-
log.Println("Seed City")
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
file, err := os.Open(
|
| 27 |
if err != nil {
|
| 28 |
return nil, err
|
| 29 |
}
|
|
@@ -36,10 +34,10 @@ func seedCity() ([]models.RegionCity, error) {
|
|
| 36 |
}
|
| 37 |
|
| 38 |
func seedProvince() ([]models.RegionProvince, error) {
|
| 39 |
-
log.Println("Seed
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
file, err := os.Open(
|
| 43 |
if err != nil {
|
| 44 |
return nil, err
|
| 45 |
}
|
|
|
|
| 4 |
"encoding/json"
|
| 5 |
"log"
|
| 6 |
"os"
|
|
|
|
|
|
|
| 7 |
|
| 8 |
"api.qobiltu.id/models"
|
| 9 |
"api.qobiltu.id/repositories"
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
func seedCity() ([]models.RegionCity, error) {
|
| 21 |
+
log.Println("Seed City..")
|
| 22 |
+
path := "utils/seeds/city.json"
|
| 23 |
+
|
| 24 |
+
file, err := os.Open(path)
|
| 25 |
if err != nil {
|
| 26 |
return nil, err
|
| 27 |
}
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
func seedProvince() ([]models.RegionProvince, error) {
|
| 37 |
+
log.Println("Seed Province..")
|
| 38 |
+
path := "utils/seeds/province.json"
|
| 39 |
+
|
| 40 |
+
file, err := os.Open(path)
|
| 41 |
if err != nil {
|
| 42 |
return nil, err
|
| 43 |
}
|
space/space/space/README.md
CHANGED
|
@@ -84,4 +84,8 @@ The API uses the `errors` package to handle errors. You can set the `ERROR_PATH`
|
|
| 84 |
|
| 85 |
### View Log container
|
| 86 |
> docker logs --tail=50 -f api-qobiltu
|
| 87 |
-
> docker logs postgres-db
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
### View Log container
|
| 86 |
> docker logs --tail=50 -f api-qobiltu
|
| 87 |
+
> docker logs postgres-db
|
| 88 |
+
|
| 89 |
+
### Menghapus Resource docker yang tidak dipakai
|
| 90 |
+
> docker system prune
|
| 91 |
+
> docker system prune -a --volumes
|
space/space/space/space/controller/user/user_profile_controller.go
CHANGED
|
@@ -9,7 +9,7 @@ import (
|
|
| 9 |
|
| 10 |
func Profile(c *gin.Context) {
|
| 11 |
userProfile := services.UserProfileService{}
|
| 12 |
-
userProfileController := controller.Controller[any, models.AccountDetails, models.
|
| 13 |
Service: &userProfile.Service,
|
| 14 |
}
|
| 15 |
userProfileController.HeaderParse(c, func() {
|
|
|
|
| 9 |
|
| 10 |
func Profile(c *gin.Context) {
|
| 11 |
userProfile := services.UserProfileService{}
|
| 12 |
+
userProfileController := controller.Controller[any, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
Service: &userProfile.Service,
|
| 14 |
}
|
| 15 |
userProfileController.HeaderParse(c, func() {
|
space/space/space/space/controller/user/user_update_profile_controller.go
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
package user
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"fmt"
|
| 5 |
-
|
| 6 |
"api.qobiltu.id/controller"
|
| 7 |
"api.qobiltu.id/models"
|
| 8 |
"api.qobiltu.id/services"
|
|
@@ -11,7 +9,7 @@ import (
|
|
| 11 |
|
| 12 |
func UpdateProfile(c *gin.Context) {
|
| 13 |
userProfile := services.UserProfileService{}
|
| 14 |
-
userUpdateProfileController := controller.Controller[models.AccountDetails, models.AccountDetails, models.
|
| 15 |
Service: &userProfile.Service,
|
| 16 |
}
|
| 17 |
|
|
@@ -19,7 +17,7 @@ func UpdateProfile(c *gin.Context) {
|
|
| 19 |
userUpdateProfileController.Service.Constructor = userUpdateProfileController.Request
|
| 20 |
userUpdateProfileController.HeaderParse(c, func() {
|
| 21 |
userUpdateProfileController.Service.Constructor.AccountID = uint(userUpdateProfileController.AccountData.UserID)
|
| 22 |
-
|
| 23 |
})
|
| 24 |
userProfile.Update()
|
| 25 |
},
|
|
|
|
| 1 |
package user
|
| 2 |
|
| 3 |
import (
|
|
|
|
|
|
|
| 4 |
"api.qobiltu.id/controller"
|
| 5 |
"api.qobiltu.id/models"
|
| 6 |
"api.qobiltu.id/services"
|
|
|
|
| 9 |
|
| 10 |
func UpdateProfile(c *gin.Context) {
|
| 11 |
userProfile := services.UserProfileService{}
|
| 12 |
+
userUpdateProfileController := controller.Controller[models.AccountDetails, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
Service: &userProfile.Service,
|
| 14 |
}
|
| 15 |
|
|
|
|
| 17 |
userUpdateProfileController.Service.Constructor = userUpdateProfileController.Request
|
| 18 |
userUpdateProfileController.HeaderParse(c, func() {
|
| 19 |
userUpdateProfileController.Service.Constructor.AccountID = uint(userUpdateProfileController.AccountData.UserID)
|
| 20 |
+
|
| 21 |
})
|
| 22 |
userProfile.Update()
|
| 23 |
},
|
space/space/space/space/logs/error_log.txt
CHANGED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
space/space/space/space/middleware/authentication_middleware.go
CHANGED
|
@@ -3,8 +3,6 @@
|
|
| 3 |
package middleware
|
| 4 |
|
| 5 |
import (
|
| 6 |
-
"fmt"
|
| 7 |
-
|
| 8 |
"api.qobiltu.id/models"
|
| 9 |
"api.qobiltu.id/services"
|
| 10 |
"api.qobiltu.id/utils"
|
|
@@ -17,7 +15,6 @@ func AuthUser(c *gin.Context) {
|
|
| 17 |
token := c.Request.Header["Authorization"]
|
| 18 |
|
| 19 |
currAccData.UserID, currAccData.VerifyStatus, currAccData.ErrVerif = services.VerifyToken(token[0])
|
| 20 |
-
fmt.Println(token[0])
|
| 21 |
|
| 22 |
if currAccData.VerifyStatus == "invalid-token" || currAccData.VerifyStatus == "expired" {
|
| 23 |
currAccData.UserID = 0
|
|
|
|
| 3 |
package middleware
|
| 4 |
|
| 5 |
import (
|
|
|
|
|
|
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
"api.qobiltu.id/services"
|
| 8 |
"api.qobiltu.id/utils"
|
|
|
|
| 15 |
token := c.Request.Header["Authorization"]
|
| 16 |
|
| 17 |
currAccData.UserID, currAccData.VerifyStatus, currAccData.ErrVerif = services.VerifyToken(token[0])
|
|
|
|
| 18 |
|
| 19 |
if currAccData.VerifyStatus == "invalid-token" || currAccData.VerifyStatus == "expired" {
|
| 20 |
currAccData.UserID = 0
|
space/space/space/space/models/response_model.go
CHANGED
|
@@ -25,3 +25,8 @@ type Options struct {
|
|
| 25 |
type OptionsResponse struct {
|
| 26 |
Options []Options `json:"options"`
|
| 27 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
type OptionsResponse struct {
|
| 26 |
Options []Options `json:"options"`
|
| 27 |
}
|
| 28 |
+
|
| 29 |
+
type UserProfileResponse struct {
|
| 30 |
+
Account Account `json:"account"`
|
| 31 |
+
Details AccountDetails `json:"details"`
|
| 32 |
+
}
|
space/space/space/space/repositories/account_repository.go
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
package repositories
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"fmt"
|
| 5 |
-
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
)
|
| 8 |
|
|
@@ -64,8 +62,6 @@ func CreateAccountDetails(accountDetails models.AccountDetails) Repository[model
|
|
| 64 |
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 65 |
accountDetails,
|
| 66 |
)
|
| 67 |
-
fmt.Println(accountDetails)
|
| 68 |
-
fmt.Println("Account ID : ", accountDetails.AccountID)
|
| 69 |
Create(repo)
|
| 70 |
return *repo
|
| 71 |
}
|
|
|
|
| 1 |
package repositories
|
| 2 |
|
| 3 |
import (
|
|
|
|
|
|
|
| 4 |
"api.qobiltu.id/models"
|
| 5 |
)
|
| 6 |
|
|
|
|
| 62 |
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 63 |
accountDetails,
|
| 64 |
)
|
|
|
|
|
|
|
| 65 |
Create(repo)
|
| 66 |
return *repo
|
| 67 |
}
|
space/space/space/space/repositories/forgot_password_repository.go
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import "api.qobiltu.id/models"
|
| 4 |
+
|
| 5 |
+
func CreateForgotPassword(forgotPassword models.ForgotPassword) Repository[models.ForgotPassword, models.ForgotPassword] {
|
| 6 |
+
repo := Construct[models.ForgotPassword, models.ForgotPassword](
|
| 7 |
+
forgotPassword,
|
| 8 |
+
)
|
| 9 |
+
Create(repo)
|
| 10 |
+
return *repo
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
func GetForgotPasswordByToken(token uint) Repository[models.ForgotPassword, models.ForgotPassword] {
|
| 14 |
+
repo := Construct[models.ForgotPassword, models.ForgotPassword](
|
| 15 |
+
models.ForgotPassword{Token: token},
|
| 16 |
+
)
|
| 17 |
+
repo.Transactions(
|
| 18 |
+
WhereGivenConstructor[models.ForgotPassword, models.ForgotPassword],
|
| 19 |
+
Find[models.ForgotPassword, models.ForgotPassword],
|
| 20 |
+
)
|
| 21 |
+
return *repo
|
| 22 |
+
}
|
space/space/space/space/router/router.go
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
|
|
|
|
|
|
| 4 |
"api.qobiltu.id/config"
|
| 5 |
"api.qobiltu.id/controller"
|
| 6 |
"github.com/gin-gonic/gin"
|
|
@@ -9,9 +11,14 @@ import (
|
|
| 9 |
func StartService() {
|
| 10 |
router := gin.Default()
|
| 11 |
router.GET("/", controller.HomeController)
|
|
|
|
| 12 |
AuthRoute(router)
|
| 13 |
UserRoute(router)
|
| 14 |
EmailRoute(router)
|
| 15 |
OptionsRoute(router)
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
}
|
|
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"log"
|
| 5 |
+
|
| 6 |
"api.qobiltu.id/config"
|
| 7 |
"api.qobiltu.id/controller"
|
| 8 |
"github.com/gin-gonic/gin"
|
|
|
|
| 11 |
func StartService() {
|
| 12 |
router := gin.Default()
|
| 13 |
router.GET("/", controller.HomeController)
|
| 14 |
+
|
| 15 |
AuthRoute(router)
|
| 16 |
UserRoute(router)
|
| 17 |
EmailRoute(router)
|
| 18 |
OptionsRoute(router)
|
| 19 |
+
|
| 20 |
+
err := router.Run(config.TCP_ADDRESS)
|
| 21 |
+
if err != nil {
|
| 22 |
+
log.Fatalf("Failed to run server: %v", err)
|
| 23 |
+
}
|
| 24 |
}
|
space/space/space/space/services/external_authentication_service.go
CHANGED
|
@@ -27,15 +27,14 @@ func (s *GoogleAuthService) Authenticate() {
|
|
| 27 |
if GoogleAuth.NoRecord {
|
| 28 |
s.Constructor.UUID = uuid.NewV4()
|
| 29 |
s.Constructor.OauthProvider = "Google"
|
| 30 |
-
|
| 31 |
-
createGoogleAuth := repositories.CreateExternalAuth(s.Constructor)
|
| 32 |
-
|
| 33 |
-
s.Error = createGoogleAuth.RowsError
|
| 34 |
-
|
| 35 |
createAccount := repositories.CreateAccount(models.Account{
|
| 36 |
Email: email.(string),
|
| 37 |
IsEmailVerified: true,
|
| 38 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
s.Error = errors.Join(s.Error, createAccount.RowsError)
|
| 40 |
}
|
| 41 |
accountData := repositories.GetAccountById(GoogleAuth.Result.AccountID)
|
|
|
|
| 27 |
if GoogleAuth.NoRecord {
|
| 28 |
s.Constructor.UUID = uuid.NewV4()
|
| 29 |
s.Constructor.OauthProvider = "Google"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
createAccount := repositories.CreateAccount(models.Account{
|
| 31 |
Email: email.(string),
|
| 32 |
IsEmailVerified: true,
|
| 33 |
})
|
| 34 |
+
s.Constructor.AccountID = createAccount.Result.Id
|
| 35 |
+
createGoogleAuth := repositories.CreateExternalAuth(s.Constructor)
|
| 36 |
+
|
| 37 |
+
s.Error = createGoogleAuth.RowsError
|
| 38 |
s.Error = errors.Join(s.Error, createAccount.RowsError)
|
| 39 |
}
|
| 40 |
accountData := repositories.GetAccountById(GoogleAuth.Result.AccountID)
|
space/space/space/space/services/user_profile_service.go
CHANGED
|
@@ -1,17 +1,51 @@
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"
|
|
|
|
| 5 |
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
"api.qobiltu.id/repositories"
|
| 8 |
)
|
| 9 |
|
| 10 |
type UserProfileService struct {
|
| 11 |
-
Service[models.AccountDetails, models.
|
| 12 |
}
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
func (s *UserProfileService) Create() {
|
|
|
|
|
|
|
| 15 |
userProfile := repositories.CreateAccountDetails(s.Constructor)
|
| 16 |
s.Error = userProfile.RowsError
|
| 17 |
if userProfile.NoRecord {
|
|
@@ -19,7 +53,10 @@ func (s *UserProfileService) Create() {
|
|
| 19 |
s.Exception.Message = "There is no account with given credentials!"
|
| 20 |
return
|
| 21 |
}
|
| 22 |
-
s.Result =
|
|
|
|
|
|
|
|
|
|
| 23 |
}
|
| 24 |
func (s *UserProfileService) Retrieve() {
|
| 25 |
userProfile := repositories.GetDetailAccountById(s.Constructor.AccountID)
|
|
@@ -29,11 +66,15 @@ func (s *UserProfileService) Retrieve() {
|
|
| 29 |
s.Exception.Message = "There is no account with given credentials!"
|
| 30 |
return
|
| 31 |
}
|
| 32 |
-
s.Result =
|
|
|
|
|
|
|
|
|
|
| 33 |
}
|
| 34 |
|
| 35 |
func (s *UserProfileService) Update() {
|
| 36 |
-
|
|
|
|
| 37 |
userProfile := repositories.UpdateAccountDetails(s.Constructor)
|
| 38 |
s.Error = userProfile.RowsError
|
| 39 |
if userProfile.NoRecord {
|
|
@@ -41,5 +82,8 @@ func (s *UserProfileService) Update() {
|
|
| 41 |
s.Exception.Message = "There is no account with given credentials!"
|
| 42 |
return
|
| 43 |
}
|
| 44 |
-
s.Result =
|
|
|
|
|
|
|
|
|
|
| 45 |
}
|
|
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"regexp"
|
| 5 |
+
"strings"
|
| 6 |
|
| 7 |
"api.qobiltu.id/models"
|
| 8 |
"api.qobiltu.id/repositories"
|
| 9 |
)
|
| 10 |
|
| 11 |
type UserProfileService struct {
|
| 12 |
+
Service[models.AccountDetails, models.UserProfileResponse]
|
| 13 |
}
|
| 14 |
|
| 15 |
+
// SanitizePhoneNumber membersihkan dan menormalkan nomor telepon ke format +62
|
| 16 |
+
func SanitizePhoneNumber(input string) string {
|
| 17 |
+
// Hilangkan semua spasi dan strip
|
| 18 |
+
input = strings.ReplaceAll(input, " ", "")
|
| 19 |
+
input = strings.ReplaceAll(input, "-", "")
|
| 20 |
+
input = strings.ReplaceAll(input, "(", "")
|
| 21 |
+
input = strings.ReplaceAll(input, ")", "")
|
| 22 |
+
|
| 23 |
+
// Hilangkan semua karakter non-digit kecuali +
|
| 24 |
+
re := regexp.MustCompile(`[^0-9\+]`)
|
| 25 |
+
input = re.ReplaceAllString(input, "")
|
| 26 |
+
|
| 27 |
+
// Handle nomor diawali 0 (contoh: 0812...) menjadi +62812...
|
| 28 |
+
if strings.HasPrefix(input, "0") {
|
| 29 |
+
input = "+62" + input[1:]
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
// Handle jika diawali dengan 62 tanpa + (contoh: 62812...)
|
| 33 |
+
if strings.HasPrefix(input, "62") && !strings.HasPrefix(input, "+62") {
|
| 34 |
+
input = "+" + input
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
// Handle jika tidak ada awalan +62 sama sekali (contoh: 8123456789)
|
| 38 |
+
if !strings.HasPrefix(input, "+62") {
|
| 39 |
+
if strings.HasPrefix(input, "8") {
|
| 40 |
+
input = "+62" + input
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
return input
|
| 45 |
+
}
|
| 46 |
func (s *UserProfileService) Create() {
|
| 47 |
+
phoneNumber := *s.Constructor.PhoneNumber
|
| 48 |
+
*s.Constructor.PhoneNumber = SanitizePhoneNumber(phoneNumber)
|
| 49 |
userProfile := repositories.CreateAccountDetails(s.Constructor)
|
| 50 |
s.Error = userProfile.RowsError
|
| 51 |
if userProfile.NoRecord {
|
|
|
|
| 53 |
s.Exception.Message = "There is no account with given credentials!"
|
| 54 |
return
|
| 55 |
}
|
| 56 |
+
s.Result = models.UserProfileResponse{
|
| 57 |
+
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 58 |
+
Details: userProfile.Result,
|
| 59 |
+
}
|
| 60 |
}
|
| 61 |
func (s *UserProfileService) Retrieve() {
|
| 62 |
userProfile := repositories.GetDetailAccountById(s.Constructor.AccountID)
|
|
|
|
| 66 |
s.Exception.Message = "There is no account with given credentials!"
|
| 67 |
return
|
| 68 |
}
|
| 69 |
+
s.Result = models.UserProfileResponse{
|
| 70 |
+
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 71 |
+
Details: userProfile.Result,
|
| 72 |
+
}
|
| 73 |
}
|
| 74 |
|
| 75 |
func (s *UserProfileService) Update() {
|
| 76 |
+
phoneNumber := *s.Constructor.PhoneNumber
|
| 77 |
+
*s.Constructor.PhoneNumber = SanitizePhoneNumber(phoneNumber)
|
| 78 |
userProfile := repositories.UpdateAccountDetails(s.Constructor)
|
| 79 |
s.Error = userProfile.RowsError
|
| 80 |
if userProfile.NoRecord {
|
|
|
|
| 82 |
s.Exception.Message = "There is no account with given credentials!"
|
| 83 |
return
|
| 84 |
}
|
| 85 |
+
s.Result = models.UserProfileResponse{
|
| 86 |
+
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 87 |
+
Details: userProfile.Result,
|
| 88 |
+
}
|
| 89 |
}
|
space/space/space/space/space/.gitignore
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
.env
|
| 2 |
vendor/
|
| 3 |
quzuu-be.exe
|
| 4 |
-
README.md
|
| 5 |
-
.qodo
|
|
|
|
|
|
|
|
|
| 1 |
.env
|
| 2 |
vendor/
|
| 3 |
quzuu-be.exe
|
| 4 |
+
README.md
|
| 5 |
+
.qodo
|
| 6 |
+
.error
|
| 7 |
+
logs/
|
space/space/space/space/space/config/config.go
CHANGED
|
@@ -9,10 +9,16 @@ import (
|
|
| 9 |
|
| 10 |
var TCP_ADDRESS string
|
| 11 |
var LOG_PATH string
|
|
|
|
| 12 |
var HOST_ADDRESS string
|
| 13 |
var HOST_PORT string
|
| 14 |
var EMAIL_VERIFICATION_DURATION int
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
func init() {
|
| 17 |
godotenv.Load()
|
| 18 |
HOST_ADDRESS = os.Getenv("HOST_ADDRESS")
|
|
@@ -20,5 +26,9 @@ func init() {
|
|
| 20 |
TCP_ADDRESS = HOST_ADDRESS + ":" + HOST_PORT
|
| 21 |
LOG_PATH = os.Getenv("LOG_PATH")
|
| 22 |
EMAIL_VERIFICATION_DURATION, _ = strconv.Atoi(os.Getenv("EMAIL_VERIFICATION_DURATION"))
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
// Menampilkan nilai variabel lingkungan
|
| 24 |
}
|
|
|
|
| 9 |
|
| 10 |
var TCP_ADDRESS string
|
| 11 |
var LOG_PATH string
|
| 12 |
+
|
| 13 |
var HOST_ADDRESS string
|
| 14 |
var HOST_PORT string
|
| 15 |
var EMAIL_VERIFICATION_DURATION int
|
| 16 |
|
| 17 |
+
var SMTP_SENDER_EMAIL string
|
| 18 |
+
var SMTP_SENDER_PASSWORD string
|
| 19 |
+
var SMTP_HOST string
|
| 20 |
+
var SMTP_PORT string
|
| 21 |
+
|
| 22 |
func init() {
|
| 23 |
godotenv.Load()
|
| 24 |
HOST_ADDRESS = os.Getenv("HOST_ADDRESS")
|
|
|
|
| 26 |
TCP_ADDRESS = HOST_ADDRESS + ":" + HOST_PORT
|
| 27 |
LOG_PATH = os.Getenv("LOG_PATH")
|
| 28 |
EMAIL_VERIFICATION_DURATION, _ = strconv.Atoi(os.Getenv("EMAIL_VERIFICATION_DURATION"))
|
| 29 |
+
SMTP_SENDER_EMAIL = os.Getenv("SMTP_SENDER_EMAIL")
|
| 30 |
+
SMTP_SENDER_PASSWORD = os.Getenv("SMTP_SENDER_PASSWORD")
|
| 31 |
+
SMTP_HOST = os.Getenv("SMTP_HOST")
|
| 32 |
+
SMTP_PORT = os.Getenv("SMTP_PORT")
|
| 33 |
// Menampilkan nilai variabel lingkungan
|
| 34 |
}
|
space/space/space/space/space/config/database_connection_config.go
CHANGED
|
@@ -60,6 +60,10 @@ func AutoMigrateAll(db *gorm.DB) {
|
|
| 60 |
&models.AcademyContent{},
|
| 61 |
&models.AcademyMaterialProgress{},
|
| 62 |
&models.AcademyContentProgress{},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
)
|
| 64 |
|
| 65 |
if err != nil {
|
|
|
|
| 60 |
&models.AcademyContent{},
|
| 61 |
&models.AcademyMaterialProgress{},
|
| 62 |
&models.AcademyContentProgress{},
|
| 63 |
+
&models.RegionCity{},
|
| 64 |
+
&models.RegionProvince{},
|
| 65 |
+
&models.OptionCategory{},
|
| 66 |
+
&models.OptionValues{},
|
| 67 |
)
|
| 68 |
|
| 69 |
if err != nil {
|
space/space/space/space/space/controller/auth/auth_external_controller.go
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package auth
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func ExternalAuth(c *gin.Context) {
|
| 11 |
+
ExternalAuthController := controller.Controller[models.ExternalAuthRequest, models.ExternalAuth, models.AuthenticatedUser]{}
|
| 12 |
+
ExternalAuthController.RequestJSON(c, func() {
|
| 13 |
+
if ExternalAuthController.Request.OauthProvider == "google" {
|
| 14 |
+
GoogleLogin := services.GoogleAuthService{}
|
| 15 |
+
ExternalAuthController.Service = &GoogleLogin.Service
|
| 16 |
+
ExternalAuthController.Service.Constructor.OauthID = ExternalAuthController.Request.OauthID
|
| 17 |
+
GoogleLogin.Authenticate()
|
| 18 |
+
}
|
| 19 |
+
})
|
| 20 |
+
}
|
space/space/space/space/space/controller/auth/auth_forgot_password_controller.go
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
package auth
|
space/space/space/space/space/controller/email/email_create_verification_controller.go
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package controller
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func CreateVerification(c *gin.Context) {
|
| 11 |
+
emailVerification := services.EmailVerificationService{}
|
| 12 |
+
emailVerificationController := controller.Controller[models.CreateVerifyEmailRequest, models.EmailVerification, models.EmailVerification]{
|
| 13 |
+
Service: &emailVerification.Service,
|
| 14 |
+
}
|
| 15 |
+
emailVerificationController.HeaderParse(c, func() {
|
| 16 |
+
emailVerificationController.Service.Constructor.AccountID = uint(emailVerificationController.AccountData.UserID)
|
| 17 |
+
emailVerification.Create()
|
| 18 |
+
emailVerificationController.Response(c)
|
| 19 |
+
})
|
| 20 |
+
|
| 21 |
+
}
|
space/space/space/space/space/controller/email/email_validate_controller.go
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package controller
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func Verify(c *gin.Context) {
|
| 11 |
+
emailVerification := services.EmailVerificationService{}
|
| 12 |
+
emailVerificationController := controller.Controller[models.CreateVerifyEmailRequest, models.EmailVerification, models.EmailVerification]{
|
| 13 |
+
Service: &emailVerification.Service,
|
| 14 |
+
}
|
| 15 |
+
emailVerificationController.HeaderParse(c, func() {
|
| 16 |
+
emailVerificationController.Service.Constructor.AccountID = uint(emailVerificationController.AccountData.UserID)
|
| 17 |
+
emailVerificationController.RequestJSON(c, func() {
|
| 18 |
+
emailVerificationController.Service.Constructor.Token = emailVerificationController.Request.Token
|
| 19 |
+
emailVerificationController.Service.Constructor.UUID = emailVerificationController.Request.UUID
|
| 20 |
+
emailVerification.Validate()
|
| 21 |
+
})
|
| 22 |
+
})
|
| 23 |
+
|
| 24 |
+
}
|
space/space/space/space/space/controller/options/option_category_controller.go
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package options
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func AddOptions(c *gin.Context) {
|
| 11 |
+
options := services.OptionService{}
|
| 12 |
+
addOptionController := controller.Controller[[]models.OptionsRequest, []models.OptionsRequest, models.OptionsResponse]{
|
| 13 |
+
Service: &options.Service,
|
| 14 |
+
}
|
| 15 |
+
addOptionController.RequestJSON(c, func() {
|
| 16 |
+
options.Constructor = addOptionController.Request
|
| 17 |
+
options.Create()
|
| 18 |
+
})
|
| 19 |
+
}
|
space/space/space/space/space/controller/options/option_value_controller.go
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package options
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func List(c *gin.Context) {
|
| 11 |
+
options := services.OptionValueService{}
|
| 12 |
+
optionValueController := controller.Controller[any, models.OptionCategory, models.Options]{
|
| 13 |
+
Service: &options.Service,
|
| 14 |
+
}
|
| 15 |
+
slug := c.Param("slug")
|
| 16 |
+
options.Constructor.OptionSlug = slug
|
| 17 |
+
options.Retrieve()
|
| 18 |
+
optionValueController.Response(c)
|
| 19 |
+
}
|
space/space/space/space/space/controller/region/city/city_list_controller.go
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package city
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"strconv"
|
| 5 |
+
|
| 6 |
+
"api.qobiltu.id/controller"
|
| 7 |
+
"api.qobiltu.id/models"
|
| 8 |
+
"api.qobiltu.id/services"
|
| 9 |
+
"github.com/gin-gonic/gin"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
func List(c *gin.Context) {
|
| 13 |
+
city := services.CityService{}
|
| 14 |
+
CityController := controller.Controller[any, models.RegionCity, []models.RegionCity]{
|
| 15 |
+
Service: &city.Service,
|
| 16 |
+
}
|
| 17 |
+
ProvinceID, _ := strconv.Atoi(c.Query("province_id"))
|
| 18 |
+
city.Constructor.ProvinceID = uint(ProvinceID)
|
| 19 |
+
city.Retrieve()
|
| 20 |
+
CityController.Response(c)
|
| 21 |
+
}
|
space/space/space/space/space/controller/region/city/city_seeds_controller.go
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package city
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func Seeds(c *gin.Context) {
|
| 11 |
+
city := services.CityService{}
|
| 12 |
+
CityController := controller.Controller[any, models.RegionCity, []models.RegionCity]{
|
| 13 |
+
Service: &city.Service,
|
| 14 |
+
}
|
| 15 |
+
city.Create()
|
| 16 |
+
CityController.Response(c)
|
| 17 |
+
}
|
space/space/space/space/space/controller/region/province/province_list_controller.go
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package province
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func List(c *gin.Context) {
|
| 11 |
+
province := services.ProvinceService{}
|
| 12 |
+
ProvinceController := controller.Controller[any, models.RegionProvince, []models.RegionProvince]{
|
| 13 |
+
Service: &province.Service,
|
| 14 |
+
}
|
| 15 |
+
province.Retrieve()
|
| 16 |
+
ProvinceController.Response(c)
|
| 17 |
+
}
|
space/space/space/space/space/controller/region/province/province_seeds_controller.go
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package province
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func Seeds(c *gin.Context) {
|
| 11 |
+
province := services.ProvinceService{}
|
| 12 |
+
ProvinceController := controller.Controller[any, models.RegionProvince, []models.RegionProvince]{
|
| 13 |
+
Service: &province.Service,
|
| 14 |
+
}
|
| 15 |
+
province.Create()
|
| 16 |
+
ProvinceController.Response(c)
|
| 17 |
+
}
|
space/space/space/space/space/go.mod
CHANGED
|
@@ -13,15 +13,26 @@ require (
|
|
| 13 |
)
|
| 14 |
|
| 15 |
require (
|
|
|
|
|
|
|
|
|
|
| 16 |
github.com/bytedance/sonic v1.13.1 // indirect
|
| 17 |
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
| 18 |
github.com/cloudwego/base64x v0.1.5 // indirect
|
|
|
|
| 19 |
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
| 20 |
github.com/gin-contrib/sse v1.0.0 // indirect
|
|
|
|
|
|
|
| 21 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 22 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 23 |
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
| 24 |
github.com/goccy/go-json v0.10.5 // indirect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
github.com/jackc/pgpassfile v1.0.0 // indirect
|
| 26 |
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
| 27 |
github.com/jackc/pgx/v5 v5.7.2 // indirect
|
|
@@ -36,14 +47,24 @@ require (
|
|
| 36 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
| 37 |
github.com/modern-go/reflect2 v1.0.2 // indirect
|
| 38 |
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
| 39 |
-
github.com/rogpeppe/go-internal v1.
|
| 40 |
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
| 41 |
github.com/ugorji/go/codec v1.2.12 // indirect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
golang.org/x/arch v0.15.0 // indirect
|
|
|
|
| 43 |
golang.org/x/net v0.37.0 // indirect
|
|
|
|
| 44 |
golang.org/x/sync v0.12.0 // indirect
|
| 45 |
golang.org/x/sys v0.31.0 // indirect
|
| 46 |
golang.org/x/text v0.23.0 // indirect
|
| 47 |
-
google.golang.org/
|
|
|
|
|
|
|
|
|
|
| 48 |
gopkg.in/yaml.v3 v3.0.1 // indirect
|
| 49 |
)
|
|
|
|
| 13 |
)
|
| 14 |
|
| 15 |
require (
|
| 16 |
+
cloud.google.com/go/auth v0.15.0 // indirect
|
| 17 |
+
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
| 18 |
+
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
| 19 |
github.com/bytedance/sonic v1.13.1 // indirect
|
| 20 |
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
| 21 |
github.com/cloudwego/base64x v0.1.5 // indirect
|
| 22 |
+
github.com/felixge/httpsnoop v1.0.4 // indirect
|
| 23 |
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
| 24 |
github.com/gin-contrib/sse v1.0.0 // indirect
|
| 25 |
+
github.com/go-logr/logr v1.4.2 // indirect
|
| 26 |
+
github.com/go-logr/stdr v1.2.2 // indirect
|
| 27 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 28 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 29 |
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
| 30 |
github.com/goccy/go-json v0.10.5 // indirect
|
| 31 |
+
github.com/google/s2a-go v0.1.9 // indirect
|
| 32 |
+
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
| 33 |
+
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
| 34 |
+
github.com/gosimple/slug v1.15.0 // indirect
|
| 35 |
+
github.com/gosimple/unidecode v1.0.1 // indirect
|
| 36 |
github.com/jackc/pgpassfile v1.0.0 // indirect
|
| 37 |
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
| 38 |
github.com/jackc/pgx/v5 v5.7.2 // indirect
|
|
|
|
| 47 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
| 48 |
github.com/modern-go/reflect2 v1.0.2 // indirect
|
| 49 |
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
| 50 |
+
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
| 51 |
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
| 52 |
github.com/ugorji/go/codec v1.2.12 // indirect
|
| 53 |
+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
| 54 |
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
|
| 55 |
+
go.opentelemetry.io/otel v1.34.0 // indirect
|
| 56 |
+
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
| 57 |
+
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
| 58 |
golang.org/x/arch v0.15.0 // indirect
|
| 59 |
+
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
| 60 |
golang.org/x/net v0.37.0 // indirect
|
| 61 |
+
golang.org/x/oauth2 v0.28.0 // indirect
|
| 62 |
golang.org/x/sync v0.12.0 // indirect
|
| 63 |
golang.org/x/sys v0.31.0 // indirect
|
| 64 |
golang.org/x/text v0.23.0 // indirect
|
| 65 |
+
google.golang.org/api v0.228.0 // indirect
|
| 66 |
+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
| 67 |
+
google.golang.org/grpc v1.71.0 // indirect
|
| 68 |
+
google.golang.org/protobuf v1.36.6 // indirect
|
| 69 |
gopkg.in/yaml.v3 v3.0.1 // indirect
|
| 70 |
)
|
space/space/space/space/space/go.sum
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
|
| 2 |
github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
| 3 |
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
|
@@ -10,12 +16,19 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|
| 10 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 11 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 12 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
|
|
|
|
|
| 13 |
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
| 14 |
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
| 15 |
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
| 16 |
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
| 17 |
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
| 18 |
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
| 20 |
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
| 21 |
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
|
@@ -31,6 +44,16 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI
|
|
| 31 |
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
| 32 |
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
| 33 |
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
| 35 |
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
| 36 |
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
|
@@ -70,6 +93,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|
| 70 |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
| 71 |
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
| 72 |
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
|
|
|
| 73 |
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
| 74 |
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
| 75 |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
@@ -88,12 +112,26 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|
| 88 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 89 |
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
| 90 |
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
|
| 92 |
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
| 93 |
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
| 94 |
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
|
|
|
|
|
|
| 95 |
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
| 96 |
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
|
|
|
|
|
| 97 |
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
| 98 |
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
| 99 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
@@ -103,8 +141,16 @@ golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
|
| 103 |
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
| 104 |
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
| 105 |
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
| 107 |
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
|
|
|
|
|
| 108 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 109 |
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
| 110 |
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
|
|
| 1 |
+
cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
|
| 2 |
+
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
|
| 3 |
+
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
| 4 |
+
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
| 5 |
+
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
| 6 |
+
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
| 7 |
github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
|
| 8 |
github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
| 9 |
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
|
|
|
| 16 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 17 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 18 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 19 |
+
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
| 20 |
+
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
| 21 |
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
| 22 |
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
| 23 |
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
| 24 |
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
| 25 |
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
| 26 |
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
| 27 |
+
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
| 28 |
+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
| 29 |
+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
| 30 |
+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
| 31 |
+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
| 32 |
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
| 33 |
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
| 34 |
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
|
|
|
| 44 |
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
| 45 |
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
| 46 |
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
| 47 |
+
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
| 48 |
+
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
| 49 |
+
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
| 50 |
+
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
| 51 |
+
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
| 52 |
+
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
| 53 |
+
github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo=
|
| 54 |
+
github.com/gosimple/slug v1.15.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
|
| 55 |
+
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
|
| 56 |
+
github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
|
| 57 |
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
| 58 |
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
| 59 |
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
|
|
|
| 93 |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
| 94 |
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
| 95 |
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
| 96 |
+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
| 97 |
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
| 98 |
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
| 99 |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
|
|
| 112 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 113 |
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
| 114 |
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
| 115 |
+
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
| 116 |
+
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
| 117 |
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
|
| 118 |
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
|
| 119 |
+
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
| 120 |
+
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
| 121 |
+
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
| 122 |
+
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
| 123 |
+
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
| 124 |
+
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
| 125 |
golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
|
| 126 |
golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
| 127 |
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
| 128 |
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
| 129 |
+
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
| 130 |
+
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
| 131 |
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
| 132 |
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
| 133 |
+
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
| 134 |
+
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
| 135 |
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
| 136 |
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
| 137 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
|
|
| 141 |
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
| 142 |
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
| 143 |
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
| 144 |
+
google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs=
|
| 145 |
+
google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4=
|
| 146 |
+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
| 147 |
+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
| 148 |
+
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
| 149 |
+
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
| 150 |
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
| 151 |
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
| 152 |
+
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
| 153 |
+
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
| 154 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 155 |
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
| 156 |
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
space/space/space/space/space/logs/error_log.txt
CHANGED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
2025/03/23 11:04:52 Error Log : ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)
|
| 2 |
-
2025/03/23 11:06:58 Error Log : ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)
|
| 3 |
-
2025/03/23 11:24:49 Error Log : WHERE conditions required
|
| 4 |
-
2025/03/23 11:58:50 Error Log : WHERE conditions required
|
| 5 |
-
2025/03/23 12:01:28 Error Log : WHERE conditions required
|
| 6 |
-
2025/03/24 19:52:15 Error Log : ERROR: nama tabel « account_details » ditentukan lebih dari satu kali (SQLSTATE 42712)
|
| 7 |
-
2025/03/24 19:53:48 Error Log : ERROR: nama tabel « account_details » ditentukan lebih dari satu kali (SQLSTATE 42712)
|
| 8 |
-
2025/03/24 19:54:14 Error Log : WHERE conditions required
|
| 9 |
-
2025/03/24 19:55:31 Error Log : ERROR: nama tabel « account_details » ditentukan lebih dari satu kali (SQLSTATE 42712)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
space/space/space/space/space/middleware/authentication_middleware.go
CHANGED
|
@@ -3,6 +3,8 @@
|
|
| 3 |
package middleware
|
| 4 |
|
| 5 |
import (
|
|
|
|
|
|
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
"api.qobiltu.id/services"
|
| 8 |
"api.qobiltu.id/utils"
|
|
@@ -13,11 +15,9 @@ func AuthUser(c *gin.Context) {
|
|
| 13 |
var currAccData models.AccountData
|
| 14 |
if c.Request.Header["Authorization"] != nil {
|
| 15 |
token := c.Request.Header["Authorization"]
|
| 16 |
-
// fmt.Println("Authorization :", token)
|
| 17 |
|
| 18 |
currAccData.UserID, currAccData.VerifyStatus, currAccData.ErrVerif = services.VerifyToken(token[0])
|
| 19 |
-
|
| 20 |
-
// fmt.Println("Verify UserID :", currAccData.UserID)
|
| 21 |
|
| 22 |
if currAccData.VerifyStatus == "invalid-token" || currAccData.VerifyStatus == "expired" {
|
| 23 |
currAccData.UserID = 0
|
|
|
|
| 3 |
package middleware
|
| 4 |
|
| 5 |
import (
|
| 6 |
+
"fmt"
|
| 7 |
+
|
| 8 |
"api.qobiltu.id/models"
|
| 9 |
"api.qobiltu.id/services"
|
| 10 |
"api.qobiltu.id/utils"
|
|
|
|
| 15 |
var currAccData models.AccountData
|
| 16 |
if c.Request.Header["Authorization"] != nil {
|
| 17 |
token := c.Request.Header["Authorization"]
|
|
|
|
| 18 |
|
| 19 |
currAccData.UserID, currAccData.VerifyStatus, currAccData.ErrVerif = services.VerifyToken(token[0])
|
| 20 |
+
fmt.Println(token[0])
|
|
|
|
| 21 |
|
| 22 |
if currAccData.VerifyStatus == "invalid-token" || currAccData.VerifyStatus == "expired" {
|
| 23 |
currAccData.UserID = 0
|
space/space/space/space/space/models/database_orm_model.go
CHANGED
|
@@ -28,7 +28,7 @@ type AccountDetails struct {
|
|
| 28 |
LastJob *string `json:"last_job"`
|
| 29 |
Gender *bool `json:"gender"`
|
| 30 |
LastEducation *string `json:"last_education"`
|
| 31 |
-
MaritalStatus *
|
| 32 |
Avatar *string `json:"avatar"`
|
| 33 |
PhoneNumber *uint `json:"phone_number"`
|
| 34 |
}
|
|
@@ -44,10 +44,11 @@ type EmailVerification struct {
|
|
| 44 |
}
|
| 45 |
|
| 46 |
type ExternalAuth struct {
|
| 47 |
-
ID uint
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
|
|
|
| 51 |
}
|
| 52 |
|
| 53 |
type FCM struct {
|
|
@@ -91,7 +92,17 @@ type AcademyContent struct {
|
|
| 91 |
AcademyMaterialID uint `json:"academy_material_id"`
|
| 92 |
Description string `json:"description"`
|
| 93 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
type AcademyMaterialProgress struct {
|
| 96 |
ID uint `gorm:"primaryKey" json:"id"`
|
| 97 |
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
|
@@ -107,6 +118,21 @@ type AcademyContentProgress struct {
|
|
| 107 |
AcademyID uint `json:"academy_id"`
|
| 108 |
}
|
| 109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
// Gorm table name settings
|
| 111 |
func (Account) TableName() string { return "account" }
|
| 112 |
func (AccountDetails) TableName() string { return "account_details" }
|
|
@@ -119,3 +145,5 @@ func (AcademyMaterial) TableName() string { return "academy_materials" }
|
|
| 119 |
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 120 |
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 121 |
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
|
|
|
|
|
|
|
|
| 28 |
LastJob *string `json:"last_job"`
|
| 29 |
Gender *bool `json:"gender"`
|
| 30 |
LastEducation *string `json:"last_education"`
|
| 31 |
+
MaritalStatus *string `json:"marital_status"`
|
| 32 |
Avatar *string `json:"avatar"`
|
| 33 |
PhoneNumber *uint `json:"phone_number"`
|
| 34 |
}
|
|
|
|
| 44 |
}
|
| 45 |
|
| 46 |
type ExternalAuth struct {
|
| 47 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 48 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 49 |
+
OauthID string `json:"oauth_id"`
|
| 50 |
+
AccountID uint `json:"account_id"`
|
| 51 |
+
OauthProvider string `json:"oauth_provider"`
|
| 52 |
}
|
| 53 |
|
| 54 |
type FCM struct {
|
|
|
|
| 92 |
AcademyMaterialID uint `json:"academy_material_id"`
|
| 93 |
Description string `json:"description"`
|
| 94 |
}
|
| 95 |
+
type OptionCategory struct {
|
| 96 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 97 |
+
OptionName string `json:"option_name"`
|
| 98 |
+
OptionSlug string `json:"option_slug"`
|
| 99 |
+
}
|
| 100 |
|
| 101 |
+
type OptionValues struct {
|
| 102 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 103 |
+
OptionCategoryID uint `json:"option_category_id"`
|
| 104 |
+
OptionValue string `json:"option_value"`
|
| 105 |
+
}
|
| 106 |
type AcademyMaterialProgress struct {
|
| 107 |
ID uint `gorm:"primaryKey" json:"id"`
|
| 108 |
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
|
|
|
| 118 |
AcademyID uint `json:"academy_id"`
|
| 119 |
}
|
| 120 |
|
| 121 |
+
type RegionProvince struct {
|
| 122 |
+
ID uint `json:"id"`
|
| 123 |
+
Name string `json:"name"`
|
| 124 |
+
Code string `json:"code"`
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
type RegionCity struct {
|
| 128 |
+
ID uint `json:"id"`
|
| 129 |
+
Type string `json:"type"`
|
| 130 |
+
Name string `json:"name"`
|
| 131 |
+
Code string `json:"code"`
|
| 132 |
+
FullCode string `json:"full_code"`
|
| 133 |
+
ProvinceID uint `json:"province_id"`
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
// Gorm table name settings
|
| 137 |
func (Account) TableName() string { return "account" }
|
| 138 |
func (AccountDetails) TableName() string { return "account_details" }
|
|
|
|
| 145 |
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 146 |
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 147 |
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
| 148 |
+
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 149 |
+
func (RegionCity) TableName() string { return "region_cities" }
|
space/space/space/space/space/models/request_model.go
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
package models
|
| 2 |
|
|
|
|
|
|
|
| 3 |
type LoginRequest struct {
|
| 4 |
Email string `json:"email" binding:"required"`
|
| 5 |
Password string `json:"password" binding:"required"`
|
|
@@ -12,11 +14,22 @@ type RegisterRequest struct {
|
|
| 12 |
Password string `json:"password" binding:"required"`
|
| 13 |
}
|
| 14 |
|
| 15 |
-
type CreateEmailVerificationRequest struct {
|
| 16 |
-
AccountID int `json:"account_id" binding:"required"`
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
type ChangePasswordRequest struct {
|
| 20 |
OldPassword string `json:"old_password" binding:"required" `
|
| 21 |
NewPassword string `json:"new_password" binding:"required" `
|
| 22 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
+
import uuid "github.com/satori/go.uuid"
|
| 4 |
+
|
| 5 |
type LoginRequest struct {
|
| 6 |
Email string `json:"email" binding:"required"`
|
| 7 |
Password string `json:"password" binding:"required"`
|
|
|
|
| 14 |
Password string `json:"password" binding:"required"`
|
| 15 |
}
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
type ChangePasswordRequest struct {
|
| 18 |
OldPassword string `json:"old_password" binding:"required" `
|
| 19 |
NewPassword string `json:"new_password" binding:"required" `
|
| 20 |
}
|
| 21 |
+
|
| 22 |
+
type CreateVerifyEmailRequest struct {
|
| 23 |
+
Token uint `json:"token" binding:"required"`
|
| 24 |
+
UUID uuid.UUID `json:"uuid" binding:"required"`
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
type OptionsRequest struct {
|
| 28 |
+
OptionName string `json:"option_name" binding:"required"`
|
| 29 |
+
OptionValue []string `json:"option_values" binding:"required"`
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
type ExternalAuthRequest struct {
|
| 33 |
+
OauthID string `json:"oauth_id" binding:"required"`
|
| 34 |
+
OauthProvider string `json:"oauth_provider" binding:"required"`
|
| 35 |
+
}
|
space/space/space/space/space/models/response_model.go
CHANGED
|
@@ -18,3 +18,10 @@ type AuthenticatedUser struct {
|
|
| 18 |
Account Account `json:"account"`
|
| 19 |
Token string `json:"token"`
|
| 20 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
Account Account `json:"account"`
|
| 19 |
Token string `json:"token"`
|
| 20 |
}
|
| 21 |
+
type Options struct {
|
| 22 |
+
OptionCategory OptionCategory `json:"option_category"`
|
| 23 |
+
OptionValues []OptionValues `json:"option_values"`
|
| 24 |
+
}
|
| 25 |
+
type OptionsResponse struct {
|
| 26 |
+
Options []Options `json:"options"`
|
| 27 |
+
}
|
space/space/space/space/space/repositories/account_repository.go
CHANGED
|
@@ -71,7 +71,6 @@ func CreateAccountDetails(accountDetails models.AccountDetails) Repository[model
|
|
| 71 |
}
|
| 72 |
|
| 73 |
func UpdateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
| 74 |
-
fmt.Println("Account ID : ", accountDetails.AccountID)
|
| 75 |
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 76 |
models.AccountDetails{AccountID: accountDetails.AccountID},
|
| 77 |
)
|
|
|
|
| 71 |
}
|
| 72 |
|
| 73 |
func UpdateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
|
|
|
| 74 |
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 75 |
models.AccountDetails{AccountID: accountDetails.AccountID},
|
| 76 |
)
|
space/space/space/space/space/repositories/email_verification_repository.go
CHANGED
|
@@ -4,15 +4,17 @@ import (
|
|
| 4 |
"time"
|
| 5 |
|
| 6 |
"api.qobiltu.id/models"
|
|
|
|
| 7 |
)
|
| 8 |
|
| 9 |
-
func CreateEmailVerification(accountId uint, dueTime time.Time, token uint) Repository[models.EmailVerification, models.EmailVerification] {
|
| 10 |
repo := Construct[models.EmailVerification, models.EmailVerification](
|
| 11 |
models.EmailVerification{
|
| 12 |
AccountID: accountId,
|
| 13 |
IsExpired: false,
|
| 14 |
ExpiredAt: dueTime,
|
| 15 |
Token: token,
|
|
|
|
| 16 |
},
|
| 17 |
)
|
| 18 |
Create(repo)
|
|
@@ -34,6 +36,18 @@ func GetEmailVerification(accountId uint, token uint) Repository[models.EmailVer
|
|
| 34 |
return *repo
|
| 35 |
}
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
func DeleteEmailVerification(token uint) Repository[models.EmailVerification, models.EmailVerification] {
|
| 38 |
repo := Construct[models.EmailVerification, models.EmailVerification](
|
| 39 |
models.EmailVerification{
|
|
|
|
| 4 |
"time"
|
| 5 |
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
+
uuid "github.com/satori/go.uuid"
|
| 8 |
)
|
| 9 |
|
| 10 |
+
func CreateEmailVerification(uuid uuid.UUID, accountId uint, dueTime time.Time, token uint) Repository[models.EmailVerification, models.EmailVerification] {
|
| 11 |
repo := Construct[models.EmailVerification, models.EmailVerification](
|
| 12 |
models.EmailVerification{
|
| 13 |
AccountID: accountId,
|
| 14 |
IsExpired: false,
|
| 15 |
ExpiredAt: dueTime,
|
| 16 |
Token: token,
|
| 17 |
+
UUID: uuid,
|
| 18 |
},
|
| 19 |
)
|
| 20 |
Create(repo)
|
|
|
|
| 36 |
return *repo
|
| 37 |
}
|
| 38 |
|
| 39 |
+
func UpdateExpiredEmailVerification(uuid uuid.UUID) Repository[models.EmailVerification, models.EmailVerification] {
|
| 40 |
+
repo := Construct[models.EmailVerification, models.EmailVerification](
|
| 41 |
+
models.EmailVerification{UUID: uuid},
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
repo.Transaction.Where("UUID = ?", uuid).First(&repo.Constructor)
|
| 45 |
+
repo.Constructor.IsExpired = true
|
| 46 |
+
repo.Transaction.Updates(repo.Constructor)
|
| 47 |
+
repo.Result = repo.Constructor
|
| 48 |
+
return *repo
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
func DeleteEmailVerification(token uint) Repository[models.EmailVerification, models.EmailVerification] {
|
| 52 |
repo := Construct[models.EmailVerification, models.EmailVerification](
|
| 53 |
models.EmailVerification{
|
space/space/space/space/space/repositories/external_auth_repository.go
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import "api.qobiltu.id/models"
|
| 4 |
+
|
| 5 |
+
func CreateExternalAuth(oauth models.ExternalAuth) Repository[models.ExternalAuth, models.ExternalAuth] {
|
| 6 |
+
repo := Construct[models.ExternalAuth, models.ExternalAuth](
|
| 7 |
+
oauth,
|
| 8 |
+
)
|
| 9 |
+
Create(repo)
|
| 10 |
+
return *repo
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
func GetExternalAuthByAccountId(accountId uint) Repository[models.ExternalAuth, []models.ExternalAuth] {
|
| 14 |
+
repo := Construct[models.ExternalAuth, []models.ExternalAuth](
|
| 15 |
+
models.ExternalAuth{
|
| 16 |
+
AccountID: accountId,
|
| 17 |
+
},
|
| 18 |
+
)
|
| 19 |
+
repo.Transactions(
|
| 20 |
+
WhereGivenConstructor[models.ExternalAuth, []models.ExternalAuth],
|
| 21 |
+
Find[models.ExternalAuth, []models.ExternalAuth],
|
| 22 |
+
)
|
| 23 |
+
return *repo
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
func GetExternalAccountByOauthId(oauthId string) Repository[models.ExternalAuth, models.ExternalAuth] {
|
| 27 |
+
repo := Construct[models.ExternalAuth, models.ExternalAuth](
|
| 28 |
+
models.ExternalAuth{
|
| 29 |
+
OauthID: oauthId,
|
| 30 |
+
},
|
| 31 |
+
)
|
| 32 |
+
repo.Transactions(
|
| 33 |
+
WhereGivenConstructor[models.ExternalAuth, models.ExternalAuth],
|
| 34 |
+
Find[models.ExternalAuth, models.ExternalAuth],
|
| 35 |
+
)
|
| 36 |
+
return *repo
|
| 37 |
+
}
|
space/space/space/space/space/repositories/option_repository.go
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
)
|
| 6 |
+
|
| 7 |
+
func CreateOptionCategory(categories models.OptionCategory) Repository[models.OptionCategory, models.OptionCategory] {
|
| 8 |
+
repo := Construct[models.OptionCategory, models.OptionCategory](
|
| 9 |
+
categories,
|
| 10 |
+
)
|
| 11 |
+
Create(repo)
|
| 12 |
+
return *repo
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
func CreateOptionValues(values models.OptionValues) Repository[models.OptionValues, models.OptionValues] {
|
| 16 |
+
repo := Construct[models.OptionValues, models.OptionValues](
|
| 17 |
+
values,
|
| 18 |
+
)
|
| 19 |
+
Create(repo)
|
| 20 |
+
return *repo
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
func GetOptionCategoryBySlug(slug string) Repository[models.OptionCategory, models.OptionCategory] {
|
| 24 |
+
repo := Construct[models.OptionCategory, models.OptionCategory](
|
| 25 |
+
models.OptionCategory{OptionSlug: slug},
|
| 26 |
+
)
|
| 27 |
+
repo.Transactions(
|
| 28 |
+
WhereGivenConstructor[models.OptionCategory, models.OptionCategory],
|
| 29 |
+
Find[models.OptionCategory, models.OptionCategory],
|
| 30 |
+
)
|
| 31 |
+
return *repo
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
func GetOptionValuesByCategoryId(categoryId uint) Repository[models.OptionValues, []models.OptionValues] {
|
| 35 |
+
repo := Construct[models.OptionValues, []models.OptionValues](
|
| 36 |
+
models.OptionValues{OptionCategoryID: categoryId},
|
| 37 |
+
)
|
| 38 |
+
repo.Transactions(
|
| 39 |
+
WhereGivenConstructor[models.OptionValues, []models.OptionValues],
|
| 40 |
+
Find[models.OptionValues, []models.OptionValues],
|
| 41 |
+
)
|
| 42 |
+
return *repo
|
| 43 |
+
}
|
space/space/space/space/space/repositories/region_repository.go
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
)
|
| 6 |
+
|
| 7 |
+
func BulkCreateProvince(provinces []models.RegionProvince) Repository[[]models.RegionProvince, []models.RegionProvince] {
|
| 8 |
+
repo := Construct[[]models.RegionProvince, []models.RegionProvince](
|
| 9 |
+
provinces,
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
Create(repo)
|
| 13 |
+
return *repo
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
func BulkCreateCity(cities []models.RegionCity) Repository[[]models.RegionCity, []models.RegionCity] {
|
| 17 |
+
repo := Construct[[]models.RegionCity, []models.RegionCity](
|
| 18 |
+
cities,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
Create(repo)
|
| 22 |
+
return *repo
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
func GetListProvinces() Repository[models.RegionProvince, []models.RegionProvince] {
|
| 26 |
+
repo := Construct[models.RegionProvince, []models.RegionProvince](
|
| 27 |
+
models.RegionProvince{},
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
repo.Transactions(
|
| 31 |
+
Find[models.RegionProvince, []models.RegionProvince],
|
| 32 |
+
)
|
| 33 |
+
return *repo
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
func GetListCitiesByProvinceId(provinceId uint) Repository[models.RegionCity, []models.RegionCity] {
|
| 37 |
+
repo := Construct[models.RegionCity, []models.RegionCity](
|
| 38 |
+
models.RegionCity{
|
| 39 |
+
ProvinceID: provinceId,
|
| 40 |
+
},
|
| 41 |
+
)
|
| 42 |
+
repo.Transactions(
|
| 43 |
+
WhereGivenConstructor[models.RegionCity, []models.RegionCity],
|
| 44 |
+
Find[models.RegionCity, []models.RegionCity],
|
| 45 |
+
)
|
| 46 |
+
return *repo
|
| 47 |
+
}
|
space/space/space/space/space/router/auth_route.go
CHANGED
|
@@ -9,6 +9,7 @@ import (
|
|
| 9 |
func AuthRoute(router *gin.Engine) {
|
| 10 |
routerGroup := router.Group("/api/v1/auth")
|
| 11 |
{
|
|
|
|
| 12 |
routerGroup.POST("/login", AuthController.Login)
|
| 13 |
routerGroup.POST("/register", AuthController.Register)
|
| 14 |
routerGroup.PUT("/change-password", middleware.AuthUser, AuthController.ChangePassword)
|
|
|
|
| 9 |
func AuthRoute(router *gin.Engine) {
|
| 10 |
routerGroup := router.Group("/api/v1/auth")
|
| 11 |
{
|
| 12 |
+
routerGroup.POST("/external-login", AuthController.ExternalAuth)
|
| 13 |
routerGroup.POST("/login", AuthController.Login)
|
| 14 |
routerGroup.POST("/register", AuthController.Register)
|
| 15 |
routerGroup.PUT("/change-password", middleware.AuthUser, AuthController.ChangePassword)
|
space/space/space/space/space/router/email_route.go
CHANGED
|
@@ -2,14 +2,14 @@ package router
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
EmailController "api.qobiltu.id/controller/email"
|
|
|
|
| 5 |
"github.com/gin-gonic/gin"
|
| 6 |
)
|
| 7 |
|
| 8 |
func EmailRoute(router *gin.Engine) {
|
| 9 |
routerGroup := router.Group("/api/v1/email")
|
| 10 |
{
|
| 11 |
-
routerGroup.POST("/verify", EmailController.
|
| 12 |
-
routerGroup.POST("/create-verification", EmailController.CreateVerification)
|
| 13 |
-
routerGroup.DELETE("/delete-verification", EmailController.DeleteVerification)
|
| 14 |
}
|
| 15 |
}
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
EmailController "api.qobiltu.id/controller/email"
|
| 5 |
+
"api.qobiltu.id/middleware"
|
| 6 |
"github.com/gin-gonic/gin"
|
| 7 |
)
|
| 8 |
|
| 9 |
func EmailRoute(router *gin.Engine) {
|
| 10 |
routerGroup := router.Group("/api/v1/email")
|
| 11 |
{
|
| 12 |
+
routerGroup.POST("/verify", middleware.AuthUser, EmailController.Verify)
|
| 13 |
+
routerGroup.POST("/create-verification", middleware.AuthUser, EmailController.CreateVerification)
|
|
|
|
| 14 |
}
|
| 15 |
}
|
space/space/space/space/space/router/options_route.go
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package router
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
OptionsController "api.qobiltu.id/controller/options"
|
| 5 |
+
CityController "api.qobiltu.id/controller/region/city"
|
| 6 |
+
ProvinceController "api.qobiltu.id/controller/region/province"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func OptionsRoute(router *gin.Engine) {
|
| 11 |
+
routerGroup := router.Group("/api/v1/options")
|
| 12 |
+
{
|
| 13 |
+
routerGroup.POST("/create", OptionsController.AddOptions)
|
| 14 |
+
routerGroup.GET("/list/:slug", OptionsController.List)
|
| 15 |
+
routerGroup.GET("/region/provinces", ProvinceController.List)
|
| 16 |
+
routerGroup.GET("/region/cities", CityController.List)
|
| 17 |
+
routerGroup.POST("/region/seed-provinces", ProvinceController.Seeds)
|
| 18 |
+
routerGroup.POST("/region/seed-cities", CityController.Seeds)
|
| 19 |
+
}
|
| 20 |
+
}
|
space/space/space/space/space/router/router.go
CHANGED
|
@@ -12,5 +12,6 @@ func StartService() {
|
|
| 12 |
AuthRoute(router)
|
| 13 |
UserRoute(router)
|
| 14 |
EmailRoute(router)
|
|
|
|
| 15 |
router.Run(config.TCP_ADDRESS)
|
| 16 |
}
|
|
|
|
| 12 |
AuthRoute(router)
|
| 13 |
UserRoute(router)
|
| 14 |
EmailRoute(router)
|
| 15 |
+
OptionsRoute(router)
|
| 16 |
router.Run(config.TCP_ADDRESS)
|
| 17 |
}
|
space/space/space/space/space/services/authentication_service.go
CHANGED
|
@@ -2,7 +2,6 @@ package services
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"errors"
|
| 5 |
-
"fmt"
|
| 6 |
|
| 7 |
"api.qobiltu.id/models"
|
| 8 |
"api.qobiltu.id/repositories"
|
|
@@ -45,15 +44,13 @@ func (s *AuthenticationService) Update(oldPassword string, newPassword string) {
|
|
| 45 |
s.Exception.Message = "Password must have at least 8 characters!"
|
| 46 |
return
|
| 47 |
}
|
| 48 |
-
accountData := repositories.
|
| 49 |
|
| 50 |
if accountData.NoRecord {
|
| 51 |
s.Exception.DataNotFound = true
|
| 52 |
s.Exception.Message = "there is no account with given credentials!"
|
| 53 |
return
|
| 54 |
}
|
| 55 |
-
fmt.Println("Result Password", accountData.Result.Password)
|
| 56 |
-
fmt.Println("old Password given", oldPassword)
|
| 57 |
if VerifyPassword(accountData.Result.Password, oldPassword) != nil {
|
| 58 |
s.Exception.Unauthorized = true
|
| 59 |
s.Exception.Message = "incorrect old password!"
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"errors"
|
|
|
|
| 5 |
|
| 6 |
"api.qobiltu.id/models"
|
| 7 |
"api.qobiltu.id/repositories"
|
|
|
|
| 44 |
s.Exception.Message = "Password must have at least 8 characters!"
|
| 45 |
return
|
| 46 |
}
|
| 47 |
+
accountData := repositories.GetAccountById(s.Constructor.Id)
|
| 48 |
|
| 49 |
if accountData.NoRecord {
|
| 50 |
s.Exception.DataNotFound = true
|
| 51 |
s.Exception.Message = "there is no account with given credentials!"
|
| 52 |
return
|
| 53 |
}
|
|
|
|
|
|
|
| 54 |
if VerifyPassword(accountData.Result.Password, oldPassword) != nil {
|
| 55 |
s.Exception.Unauthorized = true
|
| 56 |
s.Exception.Message = "incorrect old password!"
|
space/space/space/space/space/services/email_verification_service.go
CHANGED
|
@@ -1,7 +1,10 @@
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
|
|
|
|
|
|
| 4 |
"math/rand/v2"
|
|
|
|
| 5 |
"time"
|
| 6 |
|
| 7 |
"api.qobiltu.id/config"
|
|
@@ -28,20 +31,52 @@ func (s *EmailVerificationService) Create() {
|
|
| 28 |
|
| 29 |
token := uint(rand.IntN(100000))
|
| 30 |
s.Constructor.UUID = uuid.NewV4()
|
| 31 |
-
|
|
|
|
| 32 |
|
| 33 |
s.Error = repo.RowsError
|
| 34 |
s.Result = repo.Result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
}
|
| 36 |
|
| 37 |
func (s *EmailVerificationService) Validate() {
|
| 38 |
repo := repositories.GetEmailVerification(s.Constructor.AccountID, s.Constructor.Token)
|
| 39 |
s.Error = repo.RowsError
|
|
|
|
| 40 |
if repo.NoRecord {
|
| 41 |
s.Exception.DataNotFound = true
|
| 42 |
s.Exception.Message = "Invalid token!"
|
| 43 |
return
|
| 44 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
s.Result = repo.Result
|
| 46 |
}
|
| 47 |
|
|
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"fmt"
|
| 5 |
+
"log"
|
| 6 |
"math/rand/v2"
|
| 7 |
+
"net/smtp"
|
| 8 |
"time"
|
| 9 |
|
| 10 |
"api.qobiltu.id/config"
|
|
|
|
| 31 |
|
| 32 |
token := uint(rand.IntN(100000))
|
| 33 |
s.Constructor.UUID = uuid.NewV4()
|
| 34 |
+
|
| 35 |
+
repo := repositories.CreateEmailVerification(s.Constructor.UUID, s.Constructor.AccountID, dueTime, token)
|
| 36 |
|
| 37 |
s.Error = repo.RowsError
|
| 38 |
s.Result = repo.Result
|
| 39 |
+
|
| 40 |
+
// ⬇ Kirim token ke email user menggunakan SMTP
|
| 41 |
+
go func(toEmail string, token uint) {
|
| 42 |
+
from := config.SMTP_SENDER_EMAIL
|
| 43 |
+
password := config.SMTP_SENDER_PASSWORD
|
| 44 |
+
smtpHost := config.SMTP_HOST
|
| 45 |
+
smtpPort := config.SMTP_PORT
|
| 46 |
+
|
| 47 |
+
auth := smtp.PlainAuth("", from, password, smtpHost)
|
| 48 |
+
|
| 49 |
+
subject := "Email Verification Token"
|
| 50 |
+
body := fmt.Sprintf("Your verification token is: %06d\nPlease use it before it expires.", token)
|
| 51 |
+
|
| 52 |
+
msg := []byte("To: " + toEmail + "\r\n" +
|
| 53 |
+
"Subject: " + subject + "\r\n" +
|
| 54 |
+
"\r\n" +
|
| 55 |
+
body + "\r\n")
|
| 56 |
+
|
| 57 |
+
err := smtp.SendMail(smtpHost+":"+smtpPort, auth, from, []string{toEmail}, msg)
|
| 58 |
+
if err != nil {
|
| 59 |
+
log.Printf("Error sending verification email: %v", err)
|
| 60 |
+
}
|
| 61 |
+
}(accountRepo.Result.Email, token)
|
| 62 |
}
|
| 63 |
|
| 64 |
func (s *EmailVerificationService) Validate() {
|
| 65 |
repo := repositories.GetEmailVerification(s.Constructor.AccountID, s.Constructor.Token)
|
| 66 |
s.Error = repo.RowsError
|
| 67 |
+
|
| 68 |
if repo.NoRecord {
|
| 69 |
s.Exception.DataNotFound = true
|
| 70 |
s.Exception.Message = "Invalid token!"
|
| 71 |
return
|
| 72 |
}
|
| 73 |
+
|
| 74 |
+
if repo.Result.ExpiredAt.Before(time.Now()) {
|
| 75 |
+
s.Exception.Unauthorized = true
|
| 76 |
+
s.Exception.Message = "Token has expired!"
|
| 77 |
+
repositories.UpdateExpiredEmailVerification(s.Constructor.UUID)
|
| 78 |
+
return
|
| 79 |
+
}
|
| 80 |
s.Result = repo.Result
|
| 81 |
}
|
| 82 |
|
space/space/space/space/space/services/external_authentication_service.go
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
"errors"
|
| 6 |
+
|
| 7 |
+
"api.qobiltu.id/models"
|
| 8 |
+
"api.qobiltu.id/repositories"
|
| 9 |
+
uuid "github.com/satori/go.uuid"
|
| 10 |
+
"google.golang.org/api/idtoken"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type GoogleAuthService struct {
|
| 14 |
+
Service[models.ExternalAuth, models.AuthenticatedUser]
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
func (s *GoogleAuthService) Authenticate() {
|
| 18 |
+
GoogleAuth := repositories.GetExternalAccountByOauthId(s.Constructor.OauthID)
|
| 19 |
+
payload, errGoogleAuth := idtoken.Validate(context.Background(), s.Constructor.OauthID, "")
|
| 20 |
+
s.Error = errGoogleAuth
|
| 21 |
+
if errGoogleAuth != nil {
|
| 22 |
+
s.Exception.Unauthorized = true
|
| 23 |
+
s.Exception.Message = "Oauth Provider Failed Login (Google Authentication)"
|
| 24 |
+
return
|
| 25 |
+
}
|
| 26 |
+
email := payload.Claims["email"]
|
| 27 |
+
if GoogleAuth.NoRecord {
|
| 28 |
+
s.Constructor.UUID = uuid.NewV4()
|
| 29 |
+
s.Constructor.OauthProvider = "Google"
|
| 30 |
+
|
| 31 |
+
createGoogleAuth := repositories.CreateExternalAuth(s.Constructor)
|
| 32 |
+
|
| 33 |
+
s.Error = createGoogleAuth.RowsError
|
| 34 |
+
|
| 35 |
+
createAccount := repositories.CreateAccount(models.Account{
|
| 36 |
+
Email: email.(string),
|
| 37 |
+
IsEmailVerified: true,
|
| 38 |
+
})
|
| 39 |
+
s.Error = errors.Join(s.Error, createAccount.RowsError)
|
| 40 |
+
}
|
| 41 |
+
accountData := repositories.GetAccountById(GoogleAuth.Result.AccountID)
|
| 42 |
+
token, err_tok := GenerateToken(&accountData.Result)
|
| 43 |
+
|
| 44 |
+
if err_tok != nil {
|
| 45 |
+
s.Error = errors.Join(s.Error, err_tok)
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
accountData.Result.Password = "SECRET"
|
| 49 |
+
s.Result = models.AuthenticatedUser{
|
| 50 |
+
Account: accountData.Result,
|
| 51 |
+
Token: token,
|
| 52 |
+
}
|
| 53 |
+
s.Error = accountData.RowsError
|
| 54 |
+
|
| 55 |
+
}
|
space/space/space/space/space/services/option_service.go
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/repositories"
|
| 6 |
+
"github.com/gosimple/slug"
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
type OptionService struct {
|
| 10 |
+
Service[[]models.OptionsRequest, models.OptionsResponse]
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
type OptionValueService struct {
|
| 14 |
+
Service[models.OptionCategory, models.Options]
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
func (s *OptionService) Create() {
|
| 18 |
+
optionsResult := []models.Options{}
|
| 19 |
+
for _, option := range s.Constructor {
|
| 20 |
+
OptionCategoryRepo := repositories.CreateOptionCategory(
|
| 21 |
+
models.OptionCategory{
|
| 22 |
+
OptionName: option.OptionName,
|
| 23 |
+
OptionSlug: slug.Make(option.OptionName),
|
| 24 |
+
},
|
| 25 |
+
)
|
| 26 |
+
if OptionCategoryRepo.RowsError != nil {
|
| 27 |
+
OptionCategoryRepo.Transaction.Rollback()
|
| 28 |
+
s.Error = OptionCategoryRepo.RowsError
|
| 29 |
+
return
|
| 30 |
+
}
|
| 31 |
+
optionsValueResult := []models.OptionValues{}
|
| 32 |
+
for _, value := range option.OptionValue {
|
| 33 |
+
OptionValuesRepo := repositories.CreateOptionValues(
|
| 34 |
+
models.OptionValues{
|
| 35 |
+
OptionCategoryID: OptionCategoryRepo.Result.ID,
|
| 36 |
+
OptionValue: value,
|
| 37 |
+
},
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
if OptionValuesRepo.RowsError != nil {
|
| 41 |
+
OptionValuesRepo.Transaction.Rollback()
|
| 42 |
+
s.Error = OptionValuesRepo.RowsError
|
| 43 |
+
return
|
| 44 |
+
}
|
| 45 |
+
optionsValueResult = append(optionsValueResult, OptionValuesRepo.Result)
|
| 46 |
+
}
|
| 47 |
+
optionsResult = append(optionsResult, models.Options{OptionCategory: OptionCategoryRepo.Result, OptionValues: optionsValueResult})
|
| 48 |
+
}
|
| 49 |
+
s.Result = models.OptionsResponse{
|
| 50 |
+
Options: optionsResult,
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
func (s *OptionValueService) Retrieve() {
|
| 55 |
+
optionCategory := repositories.GetOptionCategoryBySlug(s.Constructor.OptionSlug)
|
| 56 |
+
if optionCategory.RowsError != nil {
|
| 57 |
+
s.Error = optionCategory.RowsError
|
| 58 |
+
return
|
| 59 |
+
}
|
| 60 |
+
optionValues := repositories.GetOptionValuesByCategoryId(optionCategory.Result.ID)
|
| 61 |
+
if optionValues.RowsError != nil {
|
| 62 |
+
s.Error = optionValues.RowsError
|
| 63 |
+
return
|
| 64 |
+
}
|
| 65 |
+
s.Result = models.Options{
|
| 66 |
+
OptionCategory: optionCategory.Result,
|
| 67 |
+
OptionValues: optionValues.Result,
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
}
|
space/space/space/space/space/services/region_service.go
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"encoding/json"
|
| 5 |
+
"log"
|
| 6 |
+
"os"
|
| 7 |
+
"path/filepath"
|
| 8 |
+
"runtime"
|
| 9 |
+
|
| 10 |
+
"api.qobiltu.id/models"
|
| 11 |
+
"api.qobiltu.id/repositories"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
type ProvinceService struct {
|
| 15 |
+
Service[models.RegionProvince, []models.RegionProvince]
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
type CityService struct {
|
| 19 |
+
Service[models.RegionCity, []models.RegionCity]
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
func seedCity() ([]models.RegionCity, error) {
|
| 23 |
+
log.Println("Seed City")
|
| 24 |
+
_, b, _, _ := runtime.Caller(0)
|
| 25 |
+
basePath := filepath.Dir(b)
|
| 26 |
+
file, err := os.Open(filepath.Join(basePath, "..", "utils", "seeds", "city.json"))
|
| 27 |
+
if err != nil {
|
| 28 |
+
return nil, err
|
| 29 |
+
}
|
| 30 |
+
defer file.Close()
|
| 31 |
+
var cities []models.RegionCity
|
| 32 |
+
if err := json.NewDecoder(file).Decode(&cities); err != nil {
|
| 33 |
+
return nil, err
|
| 34 |
+
}
|
| 35 |
+
return cities, nil
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
func seedProvince() ([]models.RegionProvince, error) {
|
| 39 |
+
log.Println("Seed City")
|
| 40 |
+
_, b, _, _ := runtime.Caller(0)
|
| 41 |
+
basePath := filepath.Dir(b)
|
| 42 |
+
file, err := os.Open(filepath.Join(basePath, "..", "utils", "seeds", "province.json"))
|
| 43 |
+
if err != nil {
|
| 44 |
+
return nil, err
|
| 45 |
+
}
|
| 46 |
+
defer file.Close()
|
| 47 |
+
var provinces []models.RegionProvince
|
| 48 |
+
if err := json.NewDecoder(file).Decode(&provinces); err != nil {
|
| 49 |
+
return nil, err
|
| 50 |
+
}
|
| 51 |
+
return provinces, nil
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
func (s *ProvinceService) Create() {
|
| 55 |
+
provinces, errSeed := seedProvince()
|
| 56 |
+
if errSeed != nil {
|
| 57 |
+
s.Error = errSeed
|
| 58 |
+
s.Exception.InternalServerError = true
|
| 59 |
+
s.Exception.Message = "Failed to seed province"
|
| 60 |
+
return
|
| 61 |
+
}
|
| 62 |
+
createProvince := repositories.BulkCreateProvince(provinces)
|
| 63 |
+
s.Error = createProvince.RowsError
|
| 64 |
+
s.Result = createProvince.Result
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
func (s *CityService) Create() {
|
| 68 |
+
cities, errSeed := seedCity()
|
| 69 |
+
if errSeed != nil {
|
| 70 |
+
s.Error = errSeed
|
| 71 |
+
s.Exception.InternalServerError = true
|
| 72 |
+
s.Exception.Message = "Failed to seed province"
|
| 73 |
+
return
|
| 74 |
+
}
|
| 75 |
+
createCity := repositories.BulkCreateCity(cities)
|
| 76 |
+
s.Error = createCity.RowsError
|
| 77 |
+
s.Result = createCity.Result
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
func (s *ProvinceService) Retrieve() {
|
| 81 |
+
Province := repositories.GetListProvinces()
|
| 82 |
+
s.Error = Province.RowsError
|
| 83 |
+
s.Result = Province.Result
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
func (s *CityService) Retrieve() {
|
| 87 |
+
cities := repositories.GetListCitiesByProvinceId(s.Constructor.ProvinceID)
|
| 88 |
+
s.Error = cities.RowsError
|
| 89 |
+
s.Result = cities.Result
|
| 90 |
+
}
|
space/space/space/space/space/space/controller/email/email_create_verification.go
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
package controller
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
"strconv"
|
| 5 |
-
|
| 6 |
"api.qobiltu.id/controller"
|
| 7 |
"api.qobiltu.id/models"
|
| 8 |
"api.qobiltu.id/services"
|
|
@@ -14,9 +12,10 @@ func CreateVerification(c *gin.Context) {
|
|
| 14 |
emailVerificationController := controller.Controller[any, models.EmailVerification, models.EmailVerification]{
|
| 15 |
Service: &emailVerification.Service,
|
| 16 |
}
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
| 22 |
}
|
|
|
|
| 1 |
package controller
|
| 2 |
|
| 3 |
import (
|
|
|
|
|
|
|
| 4 |
"api.qobiltu.id/controller"
|
| 5 |
"api.qobiltu.id/models"
|
| 6 |
"api.qobiltu.id/services"
|
|
|
|
| 12 |
emailVerificationController := controller.Controller[any, models.EmailVerification, models.EmailVerification]{
|
| 13 |
Service: &emailVerification.Service,
|
| 14 |
}
|
| 15 |
+
emailVerificationController.HeaderParse(c, func() {
|
| 16 |
+
emailVerificationController.Service.Constructor.AccountID = uint(emailVerificationController.AccountData.UserID)
|
| 17 |
+
emailVerification.Create()
|
| 18 |
+
emailVerificationController.Response(c)
|
| 19 |
+
})
|
| 20 |
+
|
| 21 |
}
|