commit b79701e87c03b5345691560c237456541b46059a Author: areeqakbr Date: Thu Feb 13 13:46:06 2025 +0700 project init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..438880e --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Output of the go coverage tool +*.out + +# Temporary files +*.tmp +*.temp + +# Build directories +_build/ +_builds/ +bin/ +out/ + +# Vendor directory +vendor/ + +# Go modules +go.sum + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*.DS_Store + +# Logs +*.log + +# Dependency directories +Godeps/ +node_modules/ + +# Environment variables +.env + +# Coverage files +coverage.out \ No newline at end of file diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..2f02bac --- /dev/null +++ b/config/config.go @@ -0,0 +1,89 @@ +package config + +import ( + "errors" + "github.com/joho/godotenv" + "os" +) + +type DbConfig struct { + DBUser string + DBPass string + DBHost string + DBPort string + DBName string +} +type LoginConfig struct { + LoginAPI string + AuthMeAPI string + LogoutAPI string +} +type TokenConfig struct { + PassiveAssetIssuer string + JwtSignatureKey []byte +} + +type ApiConfig struct { + ApiPort string +} + +type TokenApi struct { + TokenApiKey string +} + +type Config struct { + DbConfig + TokenConfig + TokenApi + ApiConfig + LoginConfig +} + +func (c *Config) readConfig() error { + if err := godotenv.Load(); err != nil { + + return errors.New("failed to load environment variables") + } + + c.DbConfig = DbConfig{ + DBHost: os.Getenv("DB_HOST"), + DBPort: os.Getenv("DB_PORT"), + DBName: os.Getenv("DB_NAME"), + DBUser: os.Getenv("DB_USER"), + DBPass: os.Getenv("DB_PASSWORD"), + } + + c.ApiConfig = ApiConfig{ + ApiPort: os.Getenv("API_PORT"), + } + + c.TokenConfig = TokenConfig{ + PassiveAssetIssuer: os.Getenv("PASSIVE_ASSET_ISSUER"), + JwtSignatureKey: []byte(os.Getenv("TOKEN_KEY")), + } + + c.TokenApi = TokenApi{ + TokenApiKey: os.Getenv("TOKEN_API_KEY"), + } + + c.LoginConfig = LoginConfig{ + LoginAPI: os.Getenv("API_LOGIN_URL"), + AuthMeAPI: os.Getenv("API_ME_URL"), + LogoutAPI: os.Getenv("API_LOGOUT_URL"), + } + + if c.ApiConfig.ApiPort == "" { + return errors.New("failed to read environment variables") + } + + return nil +} + +func NewConfig() (*Config, error) { + config := &Config{} + err := config.readConfig() + if err != nil { + return nil, err + } + return config, nil +} \ No newline at end of file diff --git a/delivery/controller/backbone_controller.go b/delivery/controller/backbone_controller.go new file mode 100644 index 0000000..bf49d93 --- /dev/null +++ b/delivery/controller/backbone_controller.go @@ -0,0 +1,62 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto/req" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type BackboneController struct { + bu usecase.BackboneUseCase + rg *gin.RouterGroup +} + +func (bc *BackboneController) Route() { + rg := bc.rg.Group("/backbone") + rg.GET("", bc.GetBackbone()) + rg.POST("", bc.CreateBackbone()) +} + +func NewBackboneController(bu usecase.BackboneUseCase, rg *gin.RouterGroup) *BackboneController { + return &BackboneController{ + bu: bu, + rg: rg, + } +} + +func (bc *BackboneController) GetBackbone() gin.HandlerFunc { + return func(c *gin.Context) { + backbones, err := bc.bu.GetAllBackbone() + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Success", backbones) + } +} + +func (bc *BackboneController) CreateBackbone() gin.HandlerFunc { + return func(c *gin.Context) { + var backboneDTO req.BackboneDTO + err := c.ShouldBindJSON(&backboneDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + err = bc.bu.CreateBackbone(backboneDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Backbone has been created", nil) + } +} \ No newline at end of file diff --git a/delivery/controller/devicePort_controller.go b/delivery/controller/devicePort_controller.go new file mode 100644 index 0000000..086d8e6 --- /dev/null +++ b/delivery/controller/devicePort_controller.go @@ -0,0 +1,62 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto/req" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type DevicePortController struct { + du usecase.DevicePortUseCase + rg *gin.RouterGroup +} + +func (dc *DevicePortController) Route() { + rg := dc.rg.Group("/device-port") + rg.GET("", dc.GetDevicePort()) + rg.POST("", dc.CreateDevicePort()) +} + +func NewDevicePortController(du usecase.DevicePortUseCase, rg *gin.RouterGroup) *DevicePortController { + return &DevicePortController{ + du: du, + rg: rg, + } +} + +func (dc *DevicePortController) GetDevicePort() gin.HandlerFunc { + return func(c *gin.Context) { + devicePorts, err := dc.du.GetAllDevicePort() + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Success", devicePorts) + } +} + +func (dc *DevicePortController) CreateDevicePort() gin.HandlerFunc { + return func(c *gin.Context) { + var devicePortDTO req.DevicePort + err := c.ShouldBindJSON(&devicePortDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + err = dc.du.CreateDevicePort(devicePortDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Device Port has been created", nil) + } +} \ No newline at end of file diff --git a/delivery/controller/devices_controller.go b/delivery/controller/devices_controller.go new file mode 100644 index 0000000..3e2a2db --- /dev/null +++ b/delivery/controller/devices_controller.go @@ -0,0 +1,62 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto/req" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type DeviceController struct { + du usecase.DeviceUseCase + rg *gin.RouterGroup +} + +func (dc *DeviceController) Route() { + rg := dc.rg.Group("/devices") + rg.POST("", dc.CreateDevice()) + rg.GET("", dc.GetAllDevices()) +} + +func NewDeviceController(du usecase.DeviceUseCase, rg *gin.RouterGroup) *DeviceController { + return &DeviceController{ + du: du, + rg: rg, + } +} + +func (dc *DeviceController) CreateDevice() gin.HandlerFunc { + return func(c *gin.Context) { + var deviceDTO req.DeviceDTO + err := c.ShouldBindJSON(&deviceDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + err = dc.du.CreateDevice(deviceDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Device has been created", nil) + } +} + +func (dc *DeviceController) GetAllDevices() gin.HandlerFunc { + return func(c *gin.Context) { + devices, err := dc.du.GetAllDevices() + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Success", devices) + } +} \ No newline at end of file diff --git a/delivery/controller/fishbone_controller.go b/delivery/controller/fishbone_controller.go new file mode 100644 index 0000000..a8604f7 --- /dev/null +++ b/delivery/controller/fishbone_controller.go @@ -0,0 +1,62 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto/req" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type FishboneController struct { + fu usecase.FishboneUseCase + rg *gin.RouterGroup +} + +func (fc *FishboneController) Route() { + rg := fc.rg.Group("/fishbone") + rg.GET("", fc.GetFishbone()) + rg.POST("", fc.CreateFishbone()) +} + +func NewFishboneController(fu usecase.FishboneUseCase, rg *gin.RouterGroup) *FishboneController { + return &FishboneController{ + fu: fu, + rg: rg, + } +} + +func (fc *FishboneController) GetFishbone() gin.HandlerFunc { + return func(c *gin.Context) { + fishbones, err := fc.fu.GetAllFishbone() + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Success", fishbones) + } +} + +func (fc *FishboneController) CreateFishbone() gin.HandlerFunc { + return func(c *gin.Context) { + var fishboneDTO req.FishboneDTO + err := c.ShouldBindJSON(&fishboneDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + err = fc.fu.CreateFishbone(fishboneDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Fishbone has been created", nil) + } +} \ No newline at end of file diff --git a/delivery/controller/tower_controller.go b/delivery/controller/tower_controller.go new file mode 100644 index 0000000..3af9600 --- /dev/null +++ b/delivery/controller/tower_controller.go @@ -0,0 +1,62 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto/req" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type TowerController struct { + tu usecase.TowerUseCase + rg *gin.RouterGroup +} + +func (tc *TowerController) Route() { + rg := tc.rg.Group("/tower") + rg.GET("", tc.GetTower()) + rg.POST("", tc.CreateTower()) +} + +func NewTowerController(tu usecase.TowerUseCase, rg *gin.RouterGroup) *TowerController { + return &TowerController{ + tu: tu, + rg: rg, + } +} + +func (tc *TowerController) GetTower() gin.HandlerFunc { + return func(c *gin.Context) { + towers, err := tc.tu.GetAll() + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Success", towers) + } +} + +func (tc *TowerController) CreateTower() gin.HandlerFunc { + return func(c *gin.Context) { + var towerDTO req.TowerDTO + err := c.ShouldBindJSON(&towerDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + err = tc.tu.Post(towerDTO) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Tower has been created", nil) + } +} \ No newline at end of file diff --git a/delivery/controller/users_controller.go b/delivery/controller/users_controller.go new file mode 100644 index 0000000..dfed6a6 --- /dev/null +++ b/delivery/controller/users_controller.go @@ -0,0 +1,67 @@ +package controller + +import ( + "net/http" + "users_management/m/model/dto" + "users_management/m/usecase" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type UsersController struct { + uc usecase.UsersUsecase + ac usecase.AuthUsecase + rg *gin.RouterGroup +} + +func (uc *UsersController) Route() { + rg:= uc.rg.Group("/users") + rg.POST("/login", uc.Login()) + rg.POST("/logout", uc.Logout()) +} + +func NewUsersController(uc usecase.UsersUsecase, ac usecase.AuthUsecase,rg *gin.RouterGroup) *UsersController { + return &UsersController{ + uc: uc, + ac: ac, + rg: rg, + } +} + +func (uc *UsersController) Login() gin.HandlerFunc { + return func(c *gin.Context) { + var login dto.UserLoginDTO + err := c.ShouldBindJSON(&login) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + token, err := uc.ac.Login(login) + + if err != nil { + common.ErrorResponses(c, http.StatusUnauthorized, err.Error()) + return + } + + + common.SingleResponses(c, "Login success", gin.H{"token": token}) + + } +} + +func (uc *UsersController) Logout() gin.HandlerFunc { + return func(c *gin.Context) { + token := c.GetHeader("Authorization") + err := uc.ac.Logout(token) + + if err != nil { + common.ErrorResponses(c, http.StatusBadRequest, err.Error()) + return + } + + common.SingleResponses(c, "Logout success", nil) + } +} \ No newline at end of file diff --git a/delivery/server.go b/delivery/server.go new file mode 100644 index 0000000..3379c78 --- /dev/null +++ b/delivery/server.go @@ -0,0 +1,58 @@ +package delivery + +import ( + "fmt" + "users_management/m/config" + "users_management/m/delivery/controller" + "users_management/m/manager" + "users_management/m/utils/common" + + "github.com/gin-gonic/gin" +) + +type Server struct { + ucManager manager.UsecaseManager + engine *gin.Engine + host string +} + +func NewServer() *Server { + cfg, err := config.NewConfig() + if err != nil { + panic(err) + } + + infraManager, err := manager.NewInfraManager(cfg) + if err != nil { + panic(err) + } + + repoManager := manager.NewRepositoryManager(infraManager) + ucManager := manager.NewUsecaseManager(repoManager, cfg) + engine := gin.Default() + engine.Use(common.LoggingToFile()) + host := fmt.Sprintf(":%s", cfg.ApiPort) + + return &Server{ + ucManager: ucManager, + engine: engine, + host: host, + } +} + +func (s *Server) setupController() { + rg := s.engine.Group("/api/v1") + controller.NewUsersController(s.ucManager.NewUserUsecase(), s.ucManager.NewAuthUsecase(),rg).Route() + controller.NewDeviceController(s.ucManager.NewDeviceUsecase(), rg).Route() + controller.NewBackboneController(s.ucManager.NewBackboneUsecase(), rg).Route() + controller.NewFishboneController(s.ucManager.NewFishboneUsecase(), rg).Route() + controller.NewTowerController(s.ucManager.NewTowerUsecase(), rg).Route() + controller.NewDevicePortController(s.ucManager.NewDevicePortUsecase(), rg).Route() +} + +func (s *Server) Run() { + s.setupController() + if err := s.engine.Run(s.host); err != nil { + panic(err) + } +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0fcf7c3 --- /dev/null +++ b/go.mod @@ -0,0 +1,48 @@ +module users_management/m + +go 1.23.1 + +require ( + github.com/gin-gonic/gin v1.10.0 + github.com/go-playground/validator/v10 v10.24.0 + github.com/google/uuid v1.6.0 + github.com/joho/godotenv v1.5.1 + gorm.io/driver/postgres v1.5.11 + gorm.io/gorm v1.25.12 +) + +require ( + github.com/bytedance/sonic v1.12.8 // indirect + github.com/bytedance/sonic/loader v0.2.3 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.0.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.14.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/main.go b/main.go new file mode 100644 index 0000000..133f817 --- /dev/null +++ b/main.go @@ -0,0 +1,7 @@ +package main + +import "users_management/m/delivery" + +func main() { + delivery.NewServer().Run() +} \ No newline at end of file diff --git a/manager/infra_manager.go b/manager/infra_manager.go new file mode 100644 index 0000000..499d3eb --- /dev/null +++ b/manager/infra_manager.go @@ -0,0 +1,44 @@ +package manager + +import ( + "fmt" + "users_management/m/config" + "gorm.io/driver/postgres" + + "gorm.io/gorm" +) + +type InfraManager interface { + Conn() *gorm.DB +} + +type infraManager struct { + db *gorm.DB + cfg *config.Config +} + +func (im *infraManager) openConn() error { + dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai", + im.cfg.DBHost, im.cfg.DBUser, im.cfg.DBPass, im.cfg.DBName, im.cfg.DBPort) + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) + if err != nil { + return err + } + im.db = db + return nil +} + +func NewInfraManager(cfg *config.Config) (InfraManager, error) { + im := &infraManager{ + cfg: cfg, + } + err := im.openConn() + if err != nil { + panic(err) + } + return im, nil +} + +func (im *infraManager) Conn() *gorm.DB { + return im.db +} diff --git a/manager/repository_manager.go b/manager/repository_manager.go new file mode 100644 index 0000000..283e91e --- /dev/null +++ b/manager/repository_manager.go @@ -0,0 +1,47 @@ +package manager + +import "users_management/m/repository" + +type RepositoryManager interface { + NewUserRepository() repository.UsersRepo + NewDeviceRepository() repository.DevicesRepo + NewBackboneRepository() repository.BackboneRepo + NewFishboneRepository() repository.FishboneRepo + NewTowerRepository() repository.TowerRepo + + NewDevicePortRepository() repository.DevicePortRepo +} + +type repositoryManager struct { + infra InfraManager +} + +func NewRepositoryManager(infra InfraManager) RepositoryManager { + return &repositoryManager{ + infra: infra, + } +} + +func (rm *repositoryManager) NewUserRepository() repository.UsersRepo { + return repository.NewUsersRepo(rm.infra.Conn()) +} + +func (rm *repositoryManager) NewDeviceRepository() repository.DevicesRepo { + return repository.NewDevicesRepo(rm.infra.Conn()) +} + +func (rm *repositoryManager) NewBackboneRepository() repository.BackboneRepo { + return repository.NewBackboneRepo(rm.infra.Conn()) +} + +func (rm *repositoryManager) NewFishboneRepository() repository.FishboneRepo { + return repository.NewFishboneRepo(rm.infra.Conn()) +} + +func (rm *repositoryManager) NewTowerRepository() repository.TowerRepo { + return repository.NewTowerRepo(rm.infra.Conn()) +} + +func (rm *repositoryManager) NewDevicePortRepository() repository.DevicePortRepo { + return repository.NewDevicePortRepo(rm.infra.Conn()) +} \ No newline at end of file diff --git a/manager/usecase_manager.go b/manager/usecase_manager.go new file mode 100644 index 0000000..4051557 --- /dev/null +++ b/manager/usecase_manager.go @@ -0,0 +1,55 @@ +package manager + +import ( + "users_management/m/config" + "users_management/m/usecase" +) + +type UsecaseManager interface { + NewUserUsecase() usecase.UsersUsecase + NewAuthUsecase() usecase.AuthUsecase + NewDeviceUsecase() usecase.DeviceUseCase + NewBackboneUsecase() usecase.BackboneUseCase + NewFishboneUsecase() usecase.FishboneUseCase + + NewTowerUsecase() usecase.TowerUseCase + + NewDevicePortUsecase() usecase.DevicePortUseCase +} + +type usecaseManager struct { + repo RepositoryManager + cfg *config.Config +} + +func NewUsecaseManager(repo RepositoryManager, cfg *config.Config) UsecaseManager { + return &usecaseManager{repo: repo,cfg: cfg } +} + +func (um *usecaseManager) NewUserUsecase() usecase.UsersUsecase { + return usecase.NewUsersUsecase(um.repo.NewUserRepository()) +} + +func (um *usecaseManager) NewAuthUsecase() usecase.AuthUsecase { + return usecase.NewAuthUsecase(um.repo.NewUserRepository(), um.cfg) +} + +func (um *usecaseManager) NewDeviceUsecase() usecase.DeviceUseCase { + return usecase.NewDeviceUseCase(um.repo.NewDeviceRepository()) +} + +func (um *usecaseManager) NewBackboneUsecase() usecase.BackboneUseCase { + return usecase.NewBackboneUseCase(um.repo.NewBackboneRepository()) +} + +func (um *usecaseManager) NewFishboneUsecase() usecase.FishboneUseCase { + return usecase.NewFishboneUseCase(um.repo.NewFishboneRepository()) +} + +func (um *usecaseManager) NewTowerUsecase() usecase.TowerUseCase { + return usecase.NewTowerUseCase(um.repo.NewTowerRepository()) +} + +func (um *usecaseManager) NewDevicePortUsecase() usecase.DevicePortUseCase { + return usecase.NewDevicePortUseCase(um.repo.NewDevicePortRepository()) +} \ No newline at end of file diff --git a/model/dto/req/backbone_dto.go b/model/dto/req/backbone_dto.go new file mode 100644 index 0000000..d674fd6 --- /dev/null +++ b/model/dto/req/backbone_dto.go @@ -0,0 +1,9 @@ +package req + +import "github.com/google/uuid" + +type BackboneDTO struct { + DeviceStartID uuid.UUID `json:"dev_start_id"` + DeviceEndID uuid.UUID `json:"dev_end_id"` + CoreAmount int `json:"core_amount"` +} \ No newline at end of file diff --git a/model/dto/req/devicePort.go b/model/dto/req/devicePort.go new file mode 100644 index 0000000..c8b821e --- /dev/null +++ b/model/dto/req/devicePort.go @@ -0,0 +1,8 @@ +package req + +import "github.com/google/uuid" + +type DevicePort struct { + DeviceID uuid.UUID `json:"device_id"` + PortNumber int `json:"port_number"` +} \ No newline at end of file diff --git a/model/dto/req/device_dto.go b/model/dto/req/device_dto.go new file mode 100644 index 0000000..fbd3f78 --- /dev/null +++ b/model/dto/req/device_dto.go @@ -0,0 +1,11 @@ +package req + + +type DeviceDTO struct { + DeviceCode string `json:"device_code" validate:"required"` + DeviceType string `json:"device_type" validate:"required"` + Longitude float64 `json:"longitude" validate:"required"` + Latitude float64 `json:"latitude" validate:"required"` + PortAmount int `json:"port_amount" validate:"required"` + Status string `json:"status" validate:"required,oneof=active inactive maintenance"` +} \ No newline at end of file diff --git a/model/dto/req/fishbone_dto.go b/model/dto/req/fishbone_dto.go new file mode 100644 index 0000000..77c0a3f --- /dev/null +++ b/model/dto/req/fishbone_dto.go @@ -0,0 +1,10 @@ +package req + +import "github.com/google/uuid" + +type FishboneDTO struct { + BackboneID uuid.UUID `json:"bb_id"` + DeviceStartID uuid.UUID `json:"dev_start_id"` + DeviceEndID uuid.UUID `json:"dev_end_id"` + CoreAmount int `json:"core_amount"` +} \ No newline at end of file diff --git a/model/dto/req/tower_dto.go b/model/dto/req/tower_dto.go new file mode 100644 index 0000000..c944583 --- /dev/null +++ b/model/dto/req/tower_dto.go @@ -0,0 +1,10 @@ +package req + +import "github.com/google/uuid" + +type TowerDTO struct { + DeviceID uuid.UUID `json:"dev_id"` + TowerCode string `json:"tower_code"` + Longitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` +} \ No newline at end of file diff --git a/model/dto/res/login_res.go b/model/dto/res/login_res.go new file mode 100644 index 0000000..394001f --- /dev/null +++ b/model/dto/res/login_res.go @@ -0,0 +1,20 @@ +package res + +type AuthResponses struct { + Token string `json:"token"` + Detail AuthMeResponse `json:"data"` +} + +type AuthMeResponse struct { + Success bool `json:"success"` + Data struct { + NomorInduk string `json:"nomor_induk"` + Username string `json:"username"` + Nama string `json:"nama"` + JenisKelamin string `json:"jenis_kelamin"` + Perusahaan string `json:"perusahaan"` + Cabang string `json:"cabang"` + Departemen string `json:"departemen"` + Jabatan string `json:"jabatan"` + } `json:"data"` +} \ No newline at end of file diff --git a/model/dto/res/register_res.go b/model/dto/res/register_res.go new file mode 100644 index 0000000..c4562b2 --- /dev/null +++ b/model/dto/res/register_res.go @@ -0,0 +1,11 @@ +package res + +type Status struct { + Code int `json:"code"` + Description string `json:"description"` +} + +type SingleResponses struct { + Status Status `json:"status"` + Data any `json:"data"` +} \ No newline at end of file diff --git a/model/dto/user_dto.go b/model/dto/user_dto.go new file mode 100644 index 0000000..1bd6858 --- /dev/null +++ b/model/dto/user_dto.go @@ -0,0 +1,13 @@ +package dto + +type UserRegisterDTO struct { + Name string `json:"name" validate:"required"` + Username string `json:"username" validate:"required"` + Password string `json:"password" validate:"required"` + RoleID string `json:"role_id" validate:"required,uuid"` +} + +type UserLoginDTO struct { + Username string `json:"username" validate:"required"` + Password string `json:"password" validate:"required"` +} \ No newline at end of file diff --git a/model/entity/backbone.go b/model/entity/backbone.go new file mode 100644 index 0000000..9bfc603 --- /dev/null +++ b/model/entity/backbone.go @@ -0,0 +1,23 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type Backbone struct { + ID uuid.UUID `json:"id"` + DeviceStartID uuid.UUID `json:"dev_start_id" gorm:"column:dev_start_id"` + DeviceEndID uuid.UUID `json:"dev_end_id" gorm:"column:dev_end_id"` + CoreAmount int `json:"core_amount"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + + DeviceStart Device `gorm:"foreignKey:DeviceStartID"` + DeviceEnd Device `gorm:"foreignKey:DeviceEndID"` +} + +func (Backbone) TableName() string { + return "backbone" +} \ No newline at end of file diff --git a/model/entity/device_port.go b/model/entity/device_port.go new file mode 100644 index 0000000..6e4e8a5 --- /dev/null +++ b/model/entity/device_port.go @@ -0,0 +1,21 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type DevicePort struct { + ID uuid.UUID `json:"id"` + DeviceID uuid.UUID `json:"device_id" gorm:"column:device_id"` + PortNumber int `json:"port_number"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + + Device Device `gorm:"foreignKey:DeviceID"` +} + +func (DevicePort) TableName() string { + return "device_ports" +} \ No newline at end of file diff --git a/model/entity/devices.go b/model/entity/devices.go new file mode 100644 index 0000000..1e36fff --- /dev/null +++ b/model/entity/devices.go @@ -0,0 +1,29 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type DeviceType string +type DeviceStatus string + +const ( + Odp DeviceType = "ODP" + activeDev DeviceStatus = "active" + inactiveDev DeviceStatus = "inactive" + maintenanceDev DeviceStatus = "maintenance" +) + +type Device struct { + ID uuid.UUID `json:"id"` + DeviceCode string `json:"device_code"` + DeviceType DeviceType `json:"device_type"` + Longitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` + PortAmount int `json:"port_amount"` + Status DeviceStatus `json:"status"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} \ No newline at end of file diff --git a/model/entity/fishbone.go b/model/entity/fishbone.go new file mode 100644 index 0000000..59a3194 --- /dev/null +++ b/model/entity/fishbone.go @@ -0,0 +1,27 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type Fishbone struct { + ID uuid.UUID `json:"id"` + BackboneID uuid.UUID `json:"backbone_id" gorm:"column:bb_id"` + DeviceStartID uuid.UUID `json:"dev_start_id" gorm:"column:dev_start_id"` + DeviceEndID uuid.UUID `json:"dev_end_id" gorm:"column:dev_end_id"` + CoreAmount int `json:"core_amount"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + + DeviceStart Device `gorm:"foreignKey:DeviceStartID"` + DeviceEnd Device `gorm:"foreignKey:DeviceEndID"` + + Backbone Backbone `gorm:"foreignKey:BackboneID"` + +} + +func (Fishbone) TableName() string { + return "fishbone" +} \ No newline at end of file diff --git a/model/entity/roles.go b/model/entity/roles.go new file mode 100644 index 0000000..ee6089f --- /dev/null +++ b/model/entity/roles.go @@ -0,0 +1,10 @@ +package entity + +import "github.com/google/uuid" + +type Role struct { + Id uuid.UUID `json:"id"` + Name string `json:"name"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} \ No newline at end of file diff --git a/model/entity/tower.go b/model/entity/tower.go new file mode 100644 index 0000000..69a0315 --- /dev/null +++ b/model/entity/tower.go @@ -0,0 +1,23 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type Tower struct { + ID uuid.UUID `json:"id"` + DeviceID uuid.UUID`json:"dev_id" gorm:"column:dev_id"` + TowerCode string `json:"tower_code"` + Longitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + + Device Device `gorm:"foreignKey:DeviceID"` +} + +func (Tower) TableName() string { + return "towers" +} \ No newline at end of file diff --git a/model/entity/users.go b/model/entity/users.go new file mode 100644 index 0000000..9a962cb --- /dev/null +++ b/model/entity/users.go @@ -0,0 +1,18 @@ +package entity + +import ( + "time" + + "github.com/google/uuid" +) + +type User struct { + ID uuid.UUID `json:"id"` + RoleID uuid.UUID `json:"role_id"` + Role Role `json:"role"` + Name string `json:"name"` + Username string `json:"username"` + Password string `json:"password"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} \ No newline at end of file diff --git a/repository/backbone_repo.go b/repository/backbone_repo.go new file mode 100644 index 0000000..70c275e --- /dev/null +++ b/repository/backbone_repo.go @@ -0,0 +1,48 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type BackboneRepo interface { + Post(backbone entity.Backbone) error + GetAll() ([]entity.Backbone, error) + Update(backbone entity.Backbone) error +} + +type backboneRepo struct { + db *gorm.DB +} + +func NewBackboneRepo(db *gorm.DB) BackboneRepo { + return &backboneRepo{ + db: db, + } +} + +func (r *backboneRepo) Post(backbone entity.Backbone) error { + err := r.db.Create(&backbone).Error + if err != nil { + return err + } + return nil +} + +func (r *backboneRepo) GetAll() ([]entity.Backbone, error) { + var backbones []entity.Backbone + err := r.db.Find(&backbones).Error + if err != nil { + return backbones, err + } + return backbones, nil +} + +func (r *backboneRepo) Update(backbone entity.Backbone) error { + err := r.db.Save(&backbone).Error + if err != nil { + return err + } + return nil +} \ No newline at end of file diff --git a/repository/devicePort_repo.go b/repository/devicePort_repo.go new file mode 100644 index 0000000..48b208e --- /dev/null +++ b/repository/devicePort_repo.go @@ -0,0 +1,48 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type DevicePortRepo interface { + Post(devicePort entity.DevicePort) error + GetAll() ([]entity.DevicePort, error) + Update(devicePort entity.DevicePort) error +} + +type devicePortRepo struct { + db *gorm.DB +} + +func NewDevicePortRepo(db *gorm.DB) DevicePortRepo { + return &devicePortRepo{ + db: db, + } +} + +func (r *devicePortRepo) Post(devicePort entity.DevicePort) error { + err := r.db.Create(&devicePort).Error + if err != nil { + return err + } + return nil +} + +func (r *devicePortRepo) GetAll() ([]entity.DevicePort, error) { + var devicePorts []entity.DevicePort + err := r.db.Find(&devicePorts).Error + if err != nil { + return devicePorts, err + } + return devicePorts, nil +} + +func (r *devicePortRepo) Update(devicePort entity.DevicePort) error { + err := r.db.Save(&devicePort).Error + if err != nil { + return err + } + return nil +} \ No newline at end of file diff --git a/repository/devices_repo.go b/repository/devices_repo.go new file mode 100644 index 0000000..5d8b2d6 --- /dev/null +++ b/repository/devices_repo.go @@ -0,0 +1,47 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type DevicesRepo interface { + Post(device entity.Device) error + GetAll() ([]entity.Device, error) + Update(device entity.Device) error +} + +type devicesRepo struct { + db *gorm.DB +} + +func NewDevicesRepo(db *gorm.DB) DevicesRepo { + return &devicesRepo{ + db: db, + } +} + +func (r *devicesRepo) Post(device entity.Device) error { + err := r.db.Create(&device).Error + if err != nil { + return err + } + return nil +} + +func (r *devicesRepo) GetAll() ([]entity.Device, error) { + var devices []entity.Device + err := r.db.Find(&devices).Error + if err != nil { + return devices, err + } + return devices, nil +} +func (r *devicesRepo) Update(device entity.Device) error { + err := r.db.Save(&device).Error + if err != nil { + return err + } + return nil +} diff --git a/repository/fishbone_repo.go b/repository/fishbone_repo.go new file mode 100644 index 0000000..966a57d --- /dev/null +++ b/repository/fishbone_repo.go @@ -0,0 +1,48 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type FishboneRepo interface { + Post(fishbone entity.Fishbone) error + GetAll() ([]entity.Fishbone, error) + Update(fishbone entity.Fishbone) error +} + +type fishboneRepo struct { + db *gorm.DB +} + +func NewFishboneRepo(db *gorm.DB) FishboneRepo { + return &fishboneRepo{ + db: db, + } +} + +func (r *fishboneRepo) Post(fishbone entity.Fishbone) error { + err := r.db.Create(&fishbone).Error + if err != nil { + return err + } + return nil +} + +func (r *fishboneRepo) GetAll() ([]entity.Fishbone, error) { + var fishbones []entity.Fishbone + err := r.db.Find(&fishbones).Error + if err != nil { + return fishbones, err + } + return fishbones, nil +} + +func (r *fishboneRepo) Update(fishbone entity.Fishbone) error { + err := r.db.Save(&fishbone).Error + if err != nil { + return err + } + return nil +} \ No newline at end of file diff --git a/repository/tower_repo.go b/repository/tower_repo.go new file mode 100644 index 0000000..63220d0 --- /dev/null +++ b/repository/tower_repo.go @@ -0,0 +1,48 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type TowerRepo interface { + Post(tower entity.Tower) error + GetAll() ([]entity.Tower, error) + Update(tower entity.Tower) error +} + +type towerRepo struct { + db *gorm.DB +} + +func NewTowerRepo(db *gorm.DB) TowerRepo { + return &towerRepo{ + db: db, + } +} + +func (r *towerRepo) Post(tower entity.Tower) error { + err := r.db.Create(&tower).Error + if err != nil { + return err + } + return nil +} + +func (r *towerRepo) GetAll() ([]entity.Tower, error) { + var towers []entity.Tower + err := r.db.Find(&towers).Error + if err != nil { + return towers, err + } + return towers, nil +} + +func (r *towerRepo) Update(tower entity.Tower) error { + err := r.db.Save(&tower).Error + if err != nil { + return err + } + return nil +} diff --git a/repository/users_repo.go b/repository/users_repo.go new file mode 100644 index 0000000..cd2ca6d --- /dev/null +++ b/repository/users_repo.go @@ -0,0 +1,50 @@ +package repository + +import ( + "users_management/m/model/entity" + + "gorm.io/gorm" +) + +type UsersRepo interface { + Post(user entity.User) error + GetRoleByDepartment(departmentName string) (entity.Role, error) + GetUserByUsername(username string) (entity.User, error) +} + +type usersRepo struct { + db *gorm.DB +} + +func NewUsersRepo(db *gorm.DB) UsersRepo { + return &usersRepo{ + db: db, + } +} + +func (r *usersRepo) Post(user entity.User) error { + err := r.db.Create(&user).Error + if err != nil { + return err + } + return nil +} + +func (r *usersRepo) GetRoleByDepartment(departmentName string) (entity.Role, error) { + var role entity.Role + err := r.db.Where("name = ?", departmentName).First(&role).Error + if err != nil { + return role, err + } + return role, nil +} + +func (r *usersRepo) GetUserByUsername(username string) (entity.User, error) { + var users entity.User + err := r.db.Where("username = ?", username).First(&users).Error + if err != nil { + return users, err + } + return users, nil +} + diff --git a/usecase/auth_usecase.go b/usecase/auth_usecase.go new file mode 100644 index 0000000..344b77d --- /dev/null +++ b/usecase/auth_usecase.go @@ -0,0 +1,181 @@ +package usecase + +import ( + "bytes" + "encoding/json" + "errors" + "io/ioutil" + "net/http" + "time" + "users_management/m/config" + "users_management/m/model/dto" + "users_management/m/model/dto/res" + "users_management/m/model/entity" + "users_management/m/repository" + "users_management/m/utils" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" + "gorm.io/gorm" +) + +type AuthUsecase interface { + Login(login dto.UserLoginDTO) (string, error) + Logout(token string) error +} + +type authUsecase struct { + userRepo repository.UsersRepo + validate *validator.Validate + cfg *config.Config +} + +func NewAuthUsecase(userRepo repository.UsersRepo, cfg *config.Config) AuthUsecase { + return &authUsecase{ + userRepo: userRepo, + validate: validator.New(), + cfg: cfg, + } +} + +func (u *authUsecase) Login(login dto.UserLoginDTO) (string, error) { + err := u.validate.Struct(login) + if err != nil { + return "", err + } + + payload, err := json.Marshal(login) + if err != nil { + return "", err + } + + req, err := http.NewRequest("POST", u.cfg.LoginAPI, bytes.NewBuffer(payload)) + if err != nil { + return "", err + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", errors.New("wrong password or username") + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var authResponse res.AuthResponses + err = json.Unmarshal(body, &authResponse) + if err != nil { + return "", err + } + + token := authResponse.Token + + meReq, err := http.NewRequest("POST", u.cfg.AuthMeAPI, nil) + if err != nil { + return "", err + } + meReq.Header.Set("Authorization", "Bearer "+token) + meReq.Header.Set("Accept", "application/json") + + meResp, err := client.Do(meReq) + if err != nil { + return "",err + } + defer meResp.Body.Close() + + if meResp.StatusCode != http.StatusOK { + return "", errors.New("failed to validate token: " + meResp.Status) + } + + meBody, err := ioutil.ReadAll(meResp.Body) + if err != nil { + return "", err + } + + var meResponse res.AuthMeResponse + err = json.Unmarshal(meBody, &meResponse) + if err != nil { + return "", err + } + + departemen := meResponse.Data.Departemen + if departemen != "Teknisi" { + return "", errors.New("user is not a technician") + } + + role , err := u.userRepo.GetRoleByDepartment(departemen) + + if err != nil { + return "", err + } + + password, err := utils.HashPassword(login.Password) + if err != nil { + return "error while hasing password: ", err + } + + isUserExist, err := u.userRepo.GetUserByUsername(login.Username) + + if isUserExist.ID != uuid.Nil { + // Validate the password + if !utils.CheckPasswordHash(login.Password, isUserExist.Password) { + return "", errors.New("incorrect password") + } + + return token, nil + }else if err != nil && err != gorm.ErrRecordNotFound { + return "ERROR WHILE SEARCHING USERNAME", err + } + + + user := entity.User{ + ID: uuid.New(), + Name: meResponse.Data.Nama, + Username: login.Username, + Password: password, + RoleID: role.Id, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + err = u.userRepo.Post(user) + if err != nil { + return "", err + } + + return token,nil +} + +func (u *authUsecase) Logout(token string) error { + req, err := http.NewRequest("POST", u.cfg.LogoutAPI, nil) + if err != nil { + return err + } + + req.Header.Set("Authorization", "Bearer "+token) + req.Header.Set("Accept", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return errors.New("failed to logout: " + resp.Status) + } + + return nil +} \ No newline at end of file diff --git a/usecase/backbone_usecase.go b/usecase/backbone_usecase.go new file mode 100644 index 0000000..a63668c --- /dev/null +++ b/usecase/backbone_usecase.go @@ -0,0 +1,56 @@ +package usecase + +import ( + "fmt" + "time" + "users_management/m/model/dto/req" + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +type BackboneUseCase interface { + CreateBackbone(backbone req.BackboneDTO) error + GetAllBackbone() ([]entity.Backbone, error) +} + +type backboneUseCase struct { + backboneRepo repository.BackboneRepo + validate *validator.Validate +} + +func NewBackboneUseCase(backboneRepo repository.BackboneRepo) BackboneUseCase { + return &backboneUseCase{ + backboneRepo: backboneRepo, + validate: validator.New(), + } +} + +func (u *backboneUseCase) CreateBackbone(backbone req.BackboneDTO) error { + err := u.validate.Struct(backbone) + if err != nil { + return fmt.Errorf("validation error: %w", err) + } + + newBackbone := entity.Backbone{ + ID: uuid.New(), + DeviceStartID: backbone.DeviceStartID, + DeviceEndID: backbone.DeviceEndID, + CoreAmount: backbone.CoreAmount, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + + return u.backboneRepo.Post(newBackbone) +} + +func (u *backboneUseCase) GetAllBackbone() ([]entity.Backbone, error) { + backbones, err := u.backboneRepo.GetAll() + if err != nil { + return backbones, err + } + return backbones, nil +} \ No newline at end of file diff --git a/usecase/devicePort_repo.go b/usecase/devicePort_repo.go new file mode 100644 index 0000000..c9eb1d5 --- /dev/null +++ b/usecase/devicePort_repo.go @@ -0,0 +1,53 @@ +package usecase + +import ( + "time" + "users_management/m/model/dto/req" + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +type DevicePortUseCase interface { + CreateDevicePort(devicePort req.DevicePort) error + GetAllDevicePort() ([]entity.DevicePort, error) +} + +type devicePortUseCase struct { + devicePortRepo repository.DevicePortRepo + validate *validator.Validate +} + +func NewDevicePortUseCase(devicePortRepo repository.DevicePortRepo) DevicePortUseCase { + return &devicePortUseCase{ + devicePortRepo: devicePortRepo, + validate: validator.New(), + } +} + +func (u *devicePortUseCase) CreateDevicePort(devicePort req.DevicePort) error { + err := u.validate.Struct(devicePort) + if err != nil { + return err + } + + newDevicePort := entity.DevicePort{ + ID: uuid.New(), + DeviceID: devicePort.DeviceID, + PortNumber: devicePort.PortNumber, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + return u.devicePortRepo.Post(newDevicePort) +} + +func (u *devicePortUseCase) GetAllDevicePort() ([]entity.DevicePort, error) { + devicePorts, err := u.devicePortRepo.GetAll() + if err != nil { + return devicePorts, err + } + return devicePorts, nil +} \ No newline at end of file diff --git a/usecase/device_usecase.go b/usecase/device_usecase.go new file mode 100644 index 0000000..e4bd796 --- /dev/null +++ b/usecase/device_usecase.go @@ -0,0 +1,58 @@ +package usecase + +import ( + "fmt" + "time" + "users_management/m/model/dto/req" + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +type DeviceUseCase interface { + CreateDevice(device req.DeviceDTO) error + GetAllDevices() ([]entity.Device, error) +} + +type deviceUseCase struct { + deviceRepo repository.DevicesRepo + validate *validator.Validate +} + +func NewDeviceUseCase(deviceRepo repository.DevicesRepo) DeviceUseCase { + return &deviceUseCase{ + deviceRepo: deviceRepo, + validate: validator.New(), + } +} + +func (u *deviceUseCase) CreateDevice(device req.DeviceDTO) error { + err := u.validate.Struct(device) + if err != nil { + return fmt.Errorf("validation error: %w", err) + } + + newDevice := entity.Device{ + ID: uuid.New(), + DeviceCode: device.DeviceCode, + DeviceType: entity.DeviceType(device.DeviceType), + Longitude: device.Longitude, + Latitude: device.Latitude, + PortAmount: device.PortAmount, + Status: entity.DeviceStatus(device.Status), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + return u.deviceRepo.Post(newDevice) +} + +func (u *deviceUseCase) GetAllDevices() ([]entity.Device, error) { + devices, err := u.deviceRepo.GetAll() + if err != nil { + return devices, err + } + return devices, nil +} \ No newline at end of file diff --git a/usecase/fishbone_usecase.go b/usecase/fishbone_usecase.go new file mode 100644 index 0000000..3697b21 --- /dev/null +++ b/usecase/fishbone_usecase.go @@ -0,0 +1,55 @@ +package usecase + +import ( + "time" + "users_management/m/model/dto/req" + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +type FishboneUseCase interface { + CreateFishbone(fishbone req.FishboneDTO) error + GetAllFishbone() ([]entity.Fishbone, error) +} + +type fishboneUsecase struct { + fishboneRepo repository.FishboneRepo + validate *validator.Validate +} + +func NewFishboneUseCase(fishboneRepo repository.FishboneRepo) FishboneUseCase { + return &fishboneUsecase{ + fishboneRepo: fishboneRepo, + validate: validator.New(), + } +} + +func (u *fishboneUsecase) CreateFishbone(fishbone req.FishboneDTO) error { + err := u.validate.Struct(fishbone) + if err != nil { + return err + } + + newFishbone := entity.Fishbone{ + ID: uuid.New(), + BackboneID: fishbone.BackboneID, + DeviceStartID: fishbone.DeviceStartID, + DeviceEndID: fishbone.DeviceEndID, + CoreAmount: fishbone.CoreAmount, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + return u.fishboneRepo.Post(newFishbone) +} + +func (u *fishboneUsecase) GetAllFishbone() ([]entity.Fishbone, error) { + fishbones, err := u.fishboneRepo.GetAll() + if err != nil { + return fishbones, err + } + return fishbones, nil +} diff --git a/usecase/tower_usecase.go b/usecase/tower_usecase.go new file mode 100644 index 0000000..5407cdb --- /dev/null +++ b/usecase/tower_usecase.go @@ -0,0 +1,55 @@ +package usecase + +import ( + "time" + "users_management/m/model/dto/req" + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/go-playground/validator/v10" + "github.com/google/uuid" +) + +type TowerUseCase interface { + Post(tower req.TowerDTO) error + GetAll() ([]entity.Tower, error) +} + +type towerUsecase struct { + towerRepo repository.TowerRepo + validate *validator.Validate +} + +func NewTowerUseCase(towerRepo repository.TowerRepo) TowerUseCase { + return &towerUsecase{ + towerRepo: towerRepo, + validate: validator.New(), + } +} + +func (u *towerUsecase) Post(tower req.TowerDTO) error { + err := u.validate.Struct(tower) + if err != nil { + return err + } + + newTower := entity.Tower{ + ID: uuid.New(), + DeviceID: tower.DeviceID, + TowerCode: tower.TowerCode, + Longitude: tower.Longitude, + Latitude: tower.Latitude, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + return u.towerRepo.Post(newTower) +} + +func (u *towerUsecase) GetAll() ([]entity.Tower, error) { + towers, err := u.towerRepo.GetAll() + if err != nil { + return towers, err + } + return towers, nil +} \ No newline at end of file diff --git a/usecase/users_usecase.go b/usecase/users_usecase.go new file mode 100644 index 0000000..19ec93f --- /dev/null +++ b/usecase/users_usecase.go @@ -0,0 +1,42 @@ +package usecase + +import ( + "users_management/m/model/entity" + "users_management/m/repository" + + "github.com/google/uuid" +) + +type UsersUsecase interface { + GetRoleByDepartment(departmentName string) (uuid.UUID, error) + GetUserByUsername(username string) (entity.User, error) +} + +type usersUsecase struct { + userRepo repository.UsersRepo +} + +func NewUsersUsecase(userRepo repository.UsersRepo) UsersUsecase { + return &usersUsecase{ + userRepo: userRepo, + } +} + + +func (u *usersUsecase) GetRoleByDepartment(departmentName string) (uuid.UUID, error) { + + role, err := u.userRepo.GetRoleByDepartment(departmentName) + if err != nil { + return uuid.Nil, err + } + return role.Id, nil +} + +func (u *usersUsecase) GetUserByUsername(username string) (entity.User, error) { + users, err := u.userRepo.GetUserByUsername(username) + if err != nil { + return users, err + } + return users, nil +} + diff --git a/utils/common/json_res.go b/utils/common/json_res.go new file mode 100644 index 0000000..7c2e60f --- /dev/null +++ b/utils/common/json_res.go @@ -0,0 +1,27 @@ +package common + +import ( + "net/http" + "users_management/m/model/dto/res" + + "github.com/gin-gonic/gin" +) + +func SingleResponses(ctx *gin.Context, description string, data any) { + ctx.JSON(http.StatusOK, res.SingleResponses{ + Status: res.Status{ + Code: http.StatusCreated, + Description: description, + }, + Data: data, + }) +} + +func ErrorResponses(ctx *gin.Context, code int, description string) { + ctx.JSON(code, res.SingleResponses{ + Status: res.Status{ + Code: code, + Description: description, + }, + }) +} \ No newline at end of file diff --git a/utils/common/logger.go b/utils/common/logger.go new file mode 100644 index 0000000..c3467bc --- /dev/null +++ b/utils/common/logger.go @@ -0,0 +1,16 @@ +package common + +import ( + "github.com/gin-gonic/gin" + "os" +) + +func LoggingToFile() gin.HandlerFunc { + logFile, err := os.OpenFile("gin.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + panic("Failed to open log file: " + err.Error()) + } + gin.DefaultWriter = logFile + return gin.Logger() + +} diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..b20dca9 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,17 @@ +package utils + +import "golang.org/x/crypto/bcrypt" + +func HashPassword(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + panic(err) + } + password = string(hash) + return password, nil +} + +func CheckPasswordHash(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} \ No newline at end of file