All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
148 lines
3.9 KiB
Go
148 lines
3.9 KiB
Go
package helpers
|
|
|
|
import (
|
|
"cargo-erp-backend/internal/config"
|
|
"cargo-erp-backend/internal/database"
|
|
"cargo-erp-backend/internal/domain"
|
|
"encoding/json"
|
|
"reflect"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
"go.uber.org/zap"
|
|
"golang.org/x/crypto/bcrypt"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type HelperInterface interface {
|
|
GetDB(key string) *gorm.DB
|
|
GetRedis(key string) *redis.Client
|
|
Config() config.ConfigInterface
|
|
Log() *zap.Logger
|
|
HashPassword(password string) string
|
|
VerifyPassword(hashedPassword, password string) bool
|
|
StringFromPtr(ptr *string) string
|
|
StructTobyte(data interface{}) ([]byte, error)
|
|
CloneStructWithoutField(input interface{}, field string) (map[string]interface{}, error)
|
|
GetAuthInfo(authinfo string) (*domain.User, error)
|
|
MapStructToStruct(source interface{}, source_tag string, target interface{}, target_tag string)
|
|
}
|
|
type Helper struct {
|
|
Conf config.ConfigInterface
|
|
DB database.DatabaseInterface
|
|
Logger *zap.Logger
|
|
RedisDB database.RedisInterface
|
|
}
|
|
|
|
func NewHelper(config config.ConfigInterface, db database.DatabaseInterface, logger *zap.Logger, dbredis database.RedisInterface) HelperInterface {
|
|
return &Helper{
|
|
Conf: config,
|
|
DB: db,
|
|
Logger: logger,
|
|
RedisDB: dbredis,
|
|
}
|
|
}
|
|
func (h *Helper) GetDB(key string) *gorm.DB {
|
|
return h.DB.Get(key)
|
|
}
|
|
func (h *Helper) GetRedis(key string) *redis.Client {
|
|
return h.RedisDB.Get(key)
|
|
}
|
|
func (h *Helper) Config() config.ConfigInterface {
|
|
return h.Conf
|
|
}
|
|
func (h *Helper) Log() *zap.Logger {
|
|
return h.Logger
|
|
}
|
|
func (h *Helper) HashPassword(password string) string {
|
|
bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
return string(bytes)
|
|
}
|
|
func (h *Helper) VerifyPassword(hashedPassword, password string) bool {
|
|
err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
|
return err == nil
|
|
}
|
|
func (h *Helper) StringFromPtr(ptr *string) string {
|
|
if ptr == nil {
|
|
return ""
|
|
}
|
|
return *ptr
|
|
}
|
|
func (h *Helper) StructTobyte(data interface{}) ([]byte, error) {
|
|
var output []byte
|
|
s, err := json.Marshal(data)
|
|
if err != nil {
|
|
return output, err
|
|
}
|
|
output = s
|
|
return output, nil
|
|
}
|
|
func (h *Helper) CloneStructWithoutField(input interface{}, field string) (map[string]interface{}, error) {
|
|
|
|
data, err := json.Marshal(input)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
|
|
if err := json.Unmarshal(data, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
if len(field) > 0 {
|
|
delete(result, field)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (h *Helper) GetAuthInfo(authinfo string) (*domain.User, error) {
|
|
|
|
var auth domain.User
|
|
if err := json.Unmarshal([]byte(authinfo), &auth); err != nil {
|
|
return nil, err
|
|
}
|
|
return &auth, nil
|
|
}
|
|
|
|
func (h *Helper) MapStructToStruct(source interface{}, source_tag string, target interface{}, target_tag string) {
|
|
srcVal := reflect.ValueOf(source)
|
|
if srcVal.Kind() == reflect.Ptr {
|
|
srcVal = srcVal.Elem()
|
|
}
|
|
srcType := srcVal.Type()
|
|
|
|
// 1. Kumpulkan data dari struct asal ke dalam map [nama_tag] -> value
|
|
jsonMap := make(map[string]reflect.Value)
|
|
for i := 0; i < srcVal.NumField(); i++ {
|
|
jsonTag := srcType.Field(i).Tag.Get(source_tag)
|
|
if jsonTag != "" && jsonTag != "-" {
|
|
jsonMap[jsonTag] = srcVal.Field(i)
|
|
}
|
|
}
|
|
|
|
tgtVal := reflect.ValueOf(target)
|
|
if tgtVal.Kind() != reflect.Ptr {
|
|
panic("target harus berupa pointer ke struct")
|
|
}
|
|
tgtVal = tgtVal.Elem()
|
|
tgtType := tgtVal.Type()
|
|
|
|
// 2. Isi struct tujuan dengan mencocokkan tag 'column'
|
|
for i := 0; i < tgtVal.NumField(); i++ {
|
|
columnTag := tgtType.Field(i).Tag.Get(target_tag)
|
|
if columnTag == "" {
|
|
continue
|
|
}
|
|
|
|
// Jika ada data di map yang cocok dengan tag column, pindahkan nilainya
|
|
if srcFieldVal, tersedia := jsonMap[columnTag]; tersedia {
|
|
targetField := tgtVal.Field(i)
|
|
|
|
// Pastikan tipe datanya sama atau bisa saling di-assign untuk menghindari panic
|
|
if targetField.CanSet() && srcFieldVal.Type().AssignableTo(targetField.Type()) {
|
|
targetField.Set(srcFieldVal)
|
|
}
|
|
}
|
|
}
|
|
}
|