Compare commits
24 Commits
41d5fda851
...
ae8ec1c3ab
Author | SHA1 | Date |
---|---|---|
|
ae8ec1c3ab | |
|
40187810ad | |
|
d1181f31a2 | |
|
b58103f8ac | |
|
d70d2b1621 | |
|
3e301f7387 | |
|
fd1d4b7c07 | |
|
4497f6db02 | |
|
0a48d7104c | |
|
dd6c3666af | |
|
d4722e4d17 | |
|
43ef003928 | |
|
6cb35a83f7 | |
|
8be115d534 | |
|
c747a20b7f | |
|
1d5433142f | |
|
b329569a79 | |
|
323157bec7 | |
|
0b8a592bf1 | |
|
0e534f5a2d | |
|
7ea71224f3 | |
|
a4ccda1227 | |
|
6d11f53425 | |
|
380a4570d9 |
|
@ -0,0 +1,60 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
m "netina/models"
|
||||
c "netina/models/commands"
|
||||
p "netina/repositories/role"
|
||||
"netina/validation"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CreateRoleHandler struct {
|
||||
Repository p.RoleCommandRepository
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (r *CreateRoleHandler) Handle(command c.CreateRoleCommand) error {
|
||||
|
||||
if err := validation.ValidateStruct(command); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
role := &m.Role{
|
||||
Name: command.Name,
|
||||
Created_at: time.Now(),
|
||||
Modified_by: command.Modified_by ,
|
||||
}
|
||||
|
||||
return r.Repository.CreateRole(role)
|
||||
}
|
||||
|
||||
|
||||
type UpdateRoleHandler struct {
|
||||
Repository p.RoleCommandRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *UpdateRoleHandler) Handle (id uint , command c.UpdateRoleCommand)(*m.Role , error) {
|
||||
if err := validation.ValidateStruct(command); err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
role := &m.Role{
|
||||
Name: command.Name,
|
||||
Modified_by: command.Modified_by,
|
||||
Modified_at: time.Now(),
|
||||
}
|
||||
|
||||
return r.Repository.UpdateRole(id , role)
|
||||
}
|
||||
|
||||
|
||||
type RemoveRoleHandler struct {
|
||||
Repository p.RoleCommandRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *RemoveRoleHandler) Handle (id uint )error {
|
||||
return r.Repository.RemoveRole(id)
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
m "netina/models"
|
||||
c "netina/models/commands"
|
||||
u "netina/repositories/user"
|
||||
"netina/validation"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CreateUserHandler struct {
|
||||
Repository u.UserCommandRepository
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (r *CreateUserHandler) Handle(command c.CreateUserCommand) error {
|
||||
|
||||
if err := validation.ValidateStruct(command); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
User := &m.User{
|
||||
Name: command.Name,
|
||||
PhoneNumber: command.PhoneNumber,
|
||||
Role_id: command.Role_id,
|
||||
Created_at: time.Now(),
|
||||
Modified_by: command.Modified_by,
|
||||
}
|
||||
|
||||
return r.Repository.CreateUser(User)
|
||||
}
|
||||
|
||||
|
||||
type UpdateUserHandler struct {
|
||||
Repository u.UserCommandRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *UpdateUserHandler) Handle (id uint , command c.UpdateUserCommand)(*m.User , error) {
|
||||
if err := validation.ValidateStruct(command); err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
User := &m.User{
|
||||
Name: command.Name,
|
||||
PhoneNumber: command.PhoneNumber,
|
||||
Role_id: command.Role_id,
|
||||
Modified_by: command.Modified_by,
|
||||
Modified_at: time.Now(),
|
||||
}
|
||||
|
||||
return r.Repository.UpdateUser(id , User)
|
||||
}
|
||||
|
||||
|
||||
type RemoveUserHandler struct {
|
||||
Repository u.UserCommandRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *RemoveUserHandler) Handle (id uint )error {
|
||||
return r.Repository.RemoveUser(id)
|
||||
}
|
|
@ -59,6 +59,18 @@ func Create_tables()error{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.AutoMigrate(&models.User{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.AutoMigrate(&models.Role{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.AutoMigrate(&models.LoginCode{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package initialize
|
||||
|
||||
import (
|
||||
"netina/database"
|
||||
m "netina/models"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
Role_repository "netina/repositories/role"
|
||||
User_repository "netina/repositories/user"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func Init()error {
|
||||
err := godotenv.Load("./config/.env")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db := database.Db()
|
||||
|
||||
role_command := Role_repository.RoleCommandRepository{DB: &db}
|
||||
role_query := Role_repository.RoleQueryRepository{DB: &db}
|
||||
user_command := User_repository.UserCommandRepository{DB: &db}
|
||||
|
||||
|
||||
|
||||
role := &m.Role{
|
||||
Name: "admin",
|
||||
|
||||
}
|
||||
|
||||
|
||||
if err := role_command.CreateRole(role) ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
tempRole , err := role_query.GetRoleByName("admin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := &m.User{
|
||||
Name: "admin",
|
||||
PhoneNumber: os.Getenv("ADMIN_NUMBER"),
|
||||
Role_id: tempRole.Role_id,
|
||||
Created_at: time.Now(),
|
||||
}
|
||||
|
||||
if err := user_command.CreateUser(user) ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
9
main.go
9
main.go
|
@ -2,7 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
db "netina/database"
|
||||
|
||||
i "netina/initialize"
|
||||
"netina/router"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -10,12 +10,17 @@ import (
|
|||
|
||||
|
||||
|
||||
|
||||
func main(){
|
||||
db.Create_tables()
|
||||
e := echo.New()
|
||||
i.Init()
|
||||
router.LoginRoutes(e)
|
||||
router.OwnerRoutes(e)
|
||||
router.LicenseRoutes(e)
|
||||
router.PlanRoutes(e)
|
||||
router.StoreRoutes(e)
|
||||
e.Logger.Fatal(e.Start(":8000"))
|
||||
router.UserRoutes(e)
|
||||
router.RoleRoutes(e)
|
||||
e.Logger.Fatal(e.Start(":8800"))
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
auth "netina/services/authentication"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func JWTMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
|
||||
|
||||
jwt := c.Request().Header.Get("Authorization")
|
||||
|
||||
claims, err := auth.ValidateUserToken(jwt)
|
||||
if err != nil {
|
||||
fmt.Println("Token validation error:", err)
|
||||
return echo.ErrUnauthorized
|
||||
}
|
||||
|
||||
//Store claims in the context
|
||||
c.Set("user", claims)
|
||||
return next(c)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type LoginCode struct {
|
||||
LoginCode_id uint `gorm:"primaryKey"`
|
||||
PhoneNumber string `gorm:"not null" validate:"required"`
|
||||
Code string `gorm:"not null" validate:"required"`
|
||||
CreatedAt time.Time `gorm:"not null"`
|
||||
ExpiresAt time.Time `gorm:"not null"`
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package models
|
||||
|
||||
type CreateRoleCommand struct {
|
||||
Name string `validate:"required"`
|
||||
Modified_by string `validate:"required"`
|
||||
}
|
||||
|
||||
type UpdateRoleCommand struct {
|
||||
Name string `validate:"required"`
|
||||
Modified_by string `validate:"required"`
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package models
|
||||
|
||||
type CreateUserCommand struct {
|
||||
Name string `validate:"required"`
|
||||
PhoneNumber string `validate:"required"`
|
||||
Role_id uint `validate:"required"`
|
||||
Modified_by string `validate:"required"`
|
||||
}
|
||||
|
||||
type UpdateUserCommand struct {
|
||||
Name string `validate:"required"`
|
||||
PhoneNumber string `validate:"required"`
|
||||
Role_id uint `validate:"required"`
|
||||
Modified_by string `validate:"required"`
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package models
|
||||
|
||||
type CreatePhoneNumber struct {
|
||||
PhoneNumber string `validate:"required"`
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type Role struct {
|
||||
Role_id uint `gorm:"primaryKey"`
|
||||
Name string `gorm:"unique;not null;validate:'required'"`
|
||||
Created_at time.Time
|
||||
Modified_at time.Time
|
||||
Modified_by string
|
||||
Is_removed bool `gorm:"default:false"`
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type User struct {
|
||||
User_id uint `gorm:"primaryKey"`
|
||||
Name string
|
||||
PhoneNumber string `gorm:"unique;not null;validate:'required'"`
|
||||
Role_id uint `gorm:"references:Role_id"`
|
||||
Role Role
|
||||
Created_at time.Time
|
||||
Modified_at time.Time
|
||||
Modified_by string
|
||||
Is_removed bool `gorm:"default:false"`
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package queries
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
r "netina/repositories/role"
|
||||
)
|
||||
|
||||
|
||||
type GetRoleHandler struct {
|
||||
Repository r.RoleQueryRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *GetRoleHandler) Handle (id uint)(*models.Role ,error) {
|
||||
return r.Repository.GetRole(id)
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package queries
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
user_repository "netina/repositories/user"
|
||||
)
|
||||
|
||||
|
||||
type GetUserByIdHandler struct {
|
||||
Repository user_repository.UserQueryRepository
|
||||
}
|
||||
|
||||
|
||||
func (r *GetUserByIdHandler) Handle (id uint)(*models.User ,error) {
|
||||
return r.Repository.GetUser(id)
|
||||
}
|
||||
|
||||
|
||||
type GetUserByPhoneNumberHandler struct {
|
||||
Repository user_repository.UserQueryRepository
|
||||
}
|
||||
|
||||
func(r *GetUserByPhoneNumberHandler) Handle(phoneNumber string)(*models.User , error) {
|
||||
return r.Repository.GetUserByPhoneNumber(phoneNumber)
|
||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
type PlanCommand interface{
|
||||
CreatePlan(o *models.Plan) error
|
||||
GetPlan(id uint)(*models.Plan , error)
|
||||
UpdatePlan(id uint , o *models.Plan)(*models.Plan , error)
|
||||
RemovePlan(id uint)error
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package Role_repository
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RoleCommand interface{
|
||||
CreateRole(o *models.Role) error
|
||||
UpdateRole(id uint , o *models.Role)(*models.Role , error)
|
||||
RemoveRole(id uint)error
|
||||
}
|
||||
|
||||
type RoleCommandRepository struct{
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
|
||||
func (r *RoleCommandRepository) CreateRole(Role *models.Role)error{
|
||||
if err := r.DB.Create(&Role).Error ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (r *RoleCommandRepository) UpdateRole(id uint , role *models.Role)(*models.Role , error){
|
||||
var temp models.Role
|
||||
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("Role_id = ?" , id).First(&temp).Error ; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
temp.Name = role.Name
|
||||
temp.Modified_at = role.Modified_at
|
||||
temp.Modified_by = role.Modified_by
|
||||
|
||||
|
||||
if err := r.DB.Save(&temp).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &temp , nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (r *RoleCommandRepository) RemoveRole(id uint)error{
|
||||
var Role models.Role
|
||||
if err := r.DB.Where("role_id = ?" , id).Model(&Role).Update("is_removed" , true).Error;err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package Role_repository
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RoleQuery interface{
|
||||
GetRole(id uint)(*models.Role , error)
|
||||
}
|
||||
|
||||
type RoleQueryRepository struct{
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
|
||||
func (r *RoleQueryRepository) GetRole(id uint)(*models.Role , error){
|
||||
var role models.Role
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("role_id = ?" , id).First(&role).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &role , nil
|
||||
}
|
||||
|
||||
|
||||
func (r *RoleQueryRepository) GetRoleByName(name string)(*models.Role , error) {
|
||||
var role models.Role
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("name = ?" , name).First(&role).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &role , nil
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package user_repository
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserCommand interface{
|
||||
CreateUser(o *models.User) error
|
||||
UpdateUser(id uint , o *models.User)(*models.User , error)
|
||||
RemoveUser(id uint)error
|
||||
}
|
||||
|
||||
type UserCommandRepository struct{
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
|
||||
func (r *UserCommandRepository) CreateUser(user *models.User)error{
|
||||
if err := r.DB.Create(&user).Error ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (r *UserCommandRepository) UpdateUser(id uint , user *models.User)(*models.User , error){
|
||||
var temp models.User
|
||||
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("user_id = ?" , id).First(&temp).Error ; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
temp.Name = user.Name
|
||||
temp.PhoneNumber = user.PhoneNumber
|
||||
temp.Role_id = user.Role_id
|
||||
temp.Modified_at = user.Modified_at
|
||||
temp.Modified_by = user.Modified_by
|
||||
|
||||
if err := r.DB.Save(&temp).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &temp , nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (r *UserCommandRepository) RemoveUser(id uint)error{
|
||||
var user models.User
|
||||
if err := r.DB.Where("user_id = ?" , id).Model(&user).Update("is_removed" , true).Error;err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package user_repository
|
||||
|
||||
import (
|
||||
"netina/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
||||
type UserQuery interface{
|
||||
GetUser(id uint)(*models.User , error)
|
||||
}
|
||||
|
||||
type UserQueryRepository struct{
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
|
||||
func (r *UserQueryRepository) GetUser(id uint)(*models.User , error){
|
||||
var user models.User
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("user_id = ?" , id).First(&user).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &user , nil
|
||||
}
|
||||
|
||||
func (r *UserQueryRepository) GetUserByPhoneNumber(phoneNumber string)(*models.User , error){
|
||||
var user models.User
|
||||
if err := r.DB.Where("is_removed = ?" , false).Where("phone_number = ?" , phoneNumber).First(&user).Error; err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
return &user , nil
|
||||
}
|
|
@ -2,43 +2,80 @@ package router
|
|||
|
||||
import (
|
||||
"netina/database"
|
||||
"netina/middlewares"
|
||||
license_repository "netina/repositories/license"
|
||||
owner_repository "netina/repositories/owner"
|
||||
plan_repository "netina/repositories/plan"
|
||||
role_repository "netina/repositories/role"
|
||||
store_repository "netina/repositories/store"
|
||||
user_repository "netina/repositories/user"
|
||||
"netina/services"
|
||||
auth "netina/services/authentication"
|
||||
a "netina/services/authorization"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func LoginRoutes(e *echo.Echo) {
|
||||
login := e.Group("/login")
|
||||
login.POST("/phonenumber" , auth.RequestCode)
|
||||
login.POST("/verifycode" , auth.Login)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func UserRoutes(e *echo.Echo){
|
||||
db := database.Db()
|
||||
user := e.Group("/user")
|
||||
user.Use(middlewares.JWTMiddleware)
|
||||
userCommandRepo := &user_repository.UserCommandRepository{DB: &db}
|
||||
userQueryRepo := &user_repository.UserQueryRepository{DB: &db}
|
||||
userService := &services.UserService{
|
||||
CommandRepo: *userCommandRepo,
|
||||
QueryRepo: *userQueryRepo,
|
||||
}
|
||||
|
||||
user.POST("/" , userService.CreateUser , a.AdminRole)
|
||||
user.GET("/:id" , userService.GetUser)
|
||||
user.GET("/phonenumber" , userService.GetUserByPhoneNumber)
|
||||
user.PUT("/:id" , userService.UpdateUser , a.AdminRole)
|
||||
user.DELETE("/:id" , userService.RemoveUser,a.AdminRole)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func OwnerRoutes(e *echo.Echo) {
|
||||
db := database.Db()
|
||||
owner := e.Group("/owner")
|
||||
owner.Use(middlewares.JWTMiddleware)
|
||||
ownerCommandRepo := &owner_repository.OwnerCommandRepository{DB: &db}
|
||||
ownerQueryRepo := &owner_repository.OwnerQueryRepository{DB: &db}
|
||||
ownerService := &services.OwnerService{
|
||||
CommandRepo: *ownerCommandRepo,
|
||||
QueryRepo: *ownerQueryRepo,
|
||||
}
|
||||
owner.POST("/",ownerService.CreateOwner)
|
||||
owner.POST("/",ownerService.CreateOwner,a.AdminRole)
|
||||
owner.GET("/:id" , ownerService.GetOwner)
|
||||
owner.PUT("/:id" , ownerService.UpdateOwner)
|
||||
owner.DELETE("/:id" , ownerService.RemoveOwner)
|
||||
owner.PUT("/:id" , ownerService.UpdateOwner,a.AdminRole)
|
||||
owner.DELETE("/:id" , ownerService.RemoveOwner,a.AdminRole)
|
||||
}
|
||||
|
||||
func LicenseRoutes(e *echo.Echo) {
|
||||
db := database.Db()
|
||||
license := e.Group("/license")
|
||||
license.Use(middlewares.JWTMiddleware)
|
||||
licenseCommandRepo := &license_repository.LicenseCommandRepository{DB: &db}
|
||||
licenseQueryRepo := &license_repository.LicenseQueryRepository{DB: &db}
|
||||
licenseService := &services.LicenseService{
|
||||
CommandRepo: *licenseCommandRepo,
|
||||
QueryRepo: *licenseQueryRepo,
|
||||
}
|
||||
license.POST("/",licenseService.CreateLicense)
|
||||
license.POST("/",licenseService.CreateLicense,a.AdminRole)
|
||||
license.GET("/:id" , licenseService.GetLicense)
|
||||
license.PUT("/:id" , licenseService.UpdateLicense)
|
||||
license.DELETE("/:id" , licenseService.RemoveLicense)
|
||||
license.PUT("/:id" , licenseService.UpdateLicense,a.AdminRole)
|
||||
license.DELETE("/:id" , licenseService.RemoveLicense,a.AdminRole)
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,16 +83,17 @@ func LicenseRoutes(e *echo.Echo) {
|
|||
func PlanRoutes(e *echo.Echo) {
|
||||
db := database.Db()
|
||||
plan := e.Group("/plan")
|
||||
plan.Use(middlewares.JWTMiddleware)
|
||||
planCommandRepo := &plan_repository.PlanCommandRepository{DB: &db}
|
||||
planQueryRepo := &plan_repository.PlanQueryRepository{DB: &db}
|
||||
planService := &services.PlanService{
|
||||
CommandRepo: *planCommandRepo,
|
||||
QueryRepo: *planQueryRepo,
|
||||
}
|
||||
plan.POST("/",planService.CreatePlan)
|
||||
plan.POST("/",planService.CreatePlan,a.AdminRole)
|
||||
plan.GET("/:id" , planService.GetPlan)
|
||||
plan.PUT("/:id" , planService.UpdatePlan)
|
||||
plan.DELETE("/:id" , planService.RemovePlan)
|
||||
plan.PUT("/:id" , planService.UpdatePlan,a.AdminRole)
|
||||
plan.DELETE("/:id" , planService.RemovePlan,a.AdminRole)
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,16 +101,36 @@ func PlanRoutes(e *echo.Echo) {
|
|||
func StoreRoutes(e *echo.Echo) {
|
||||
db := database.Db()
|
||||
store := e.Group("/store")
|
||||
store.Use(middlewares.JWTMiddleware)
|
||||
storeCommandRepo := &store_repository.StoreCommandRepository{DB: &db}
|
||||
storeQueryRepo := &store_repository.StoreQueryRepository{DB: &db}
|
||||
storeService := &services.StoreService{
|
||||
CommandRepo: *storeCommandRepo,
|
||||
QueryRepo: *storeQueryRepo,
|
||||
}
|
||||
store.POST("/",storeService.CreateStore)
|
||||
store.POST("/",storeService.CreateStore,a.AdminRole)
|
||||
store.GET("/:id" , storeService.GetStore)
|
||||
store.GET("/owner/:id" , storeService.GetStoresList)
|
||||
store.PUT("/:id" , storeService.UpdateStore)
|
||||
store.DELETE("/:id" , storeService.RemoveStore)
|
||||
store.PUT("/:id" , storeService.UpdateStore,a.AdminRole)
|
||||
store.DELETE("/:id" , storeService.RemoveStore,a.AdminRole)
|
||||
}
|
||||
|
||||
|
||||
func RoleRoutes(e *echo.Echo) {
|
||||
db := database.Db()
|
||||
role := e.Group("/role")
|
||||
role.Use(middlewares.JWTMiddleware)
|
||||
roleCommandRepo := &role_repository.RoleCommandRepository{DB: &db}
|
||||
roleQueryRepo := &role_repository.RoleQueryRepository{DB: &db}
|
||||
roleService := &services.RoleService{
|
||||
CommandRepo: *roleCommandRepo,
|
||||
QueryRepo: *roleQueryRepo,
|
||||
}
|
||||
role.POST("/",roleService.CreateRole,a.AdminRole)
|
||||
role.GET("/:id" , roleService.GetRole)
|
||||
role.PUT("/:id" , roleService.UpdateRole,a.AdminRole)
|
||||
role.DELETE("/:id" , roleService.RemoveRole,a.AdminRole)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package authentication
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"netina/models"
|
||||
"time"
|
||||
|
||||
"netina/validation"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type GenerateCode struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewGenerateCode(db *gorm.DB) *GenerateCode {
|
||||
return &GenerateCode{DB: db}
|
||||
}
|
||||
|
||||
// Generate a random 6-digit code
|
||||
func generateCode() string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return fmt.Sprintf("%06d", rand.Intn(1000000))
|
||||
}
|
||||
|
||||
// CreateLoginCode generates a login code and stores it in the database
|
||||
func (s *GenerateCode) CreateLoginCode(phoneNumber string) (string, error) {
|
||||
var code string
|
||||
var isUnique bool
|
||||
|
||||
// Try to generate a unique code
|
||||
for !isUnique {
|
||||
code = generateCode()
|
||||
isUnique, _ = s.isCodeUnique(code)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
expiresAt := now.Add(2 * time.Minute)
|
||||
|
||||
loginCode := &models.LoginCode{
|
||||
PhoneNumber: phoneNumber,
|
||||
Code: code,
|
||||
CreatedAt: now,
|
||||
ExpiresAt: expiresAt,
|
||||
}
|
||||
|
||||
if err := validation.ValidateStruct(loginCode); err != nil {
|
||||
return "" , err
|
||||
}
|
||||
|
||||
if err := s.DB.Create(loginCode).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// Check if the generated code is unique
|
||||
func (s *GenerateCode) isCodeUnique(code string) (bool, error) {
|
||||
var loginCode models.LoginCode
|
||||
if err := s.DB.Where("code = ?", code).First(&loginCode).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// VerifyLoginCode verifies the login code and checks if it is still valid
|
||||
func (s *GenerateCode) VerifyLoginCode(phoneNumber, code string) error {
|
||||
var loginCode models.LoginCode
|
||||
|
||||
// Find the login code
|
||||
if err := s.DB.Where("phone_number = ? AND code = ?", phoneNumber, code).First(&loginCode).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New("code not found")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the code has expired
|
||||
if time.Now().After(loginCode.ExpiresAt) {
|
||||
return errors.New("code expired")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package authentication
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"netina/database"
|
||||
Role_repository "netina/repositories/role"
|
||||
User_repository "netina/repositories/user"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// JWTClaims defines the structure of JWT claims.
|
||||
type JWTClaims struct {
|
||||
ID uint `json:"id"`
|
||||
Role string `json:"role"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// Load the environment variables from the .env file
|
||||
func loadEnv() {
|
||||
err := godotenv.Load("./config/.env")
|
||||
if err != nil {
|
||||
panic("Error loading .env file")
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateJWT generates a new JWT token.
|
||||
func GenerateJWT(claims *JWTClaims) (string, error) {
|
||||
loadEnv()
|
||||
secretKey := os.Getenv("SECRET_KEY")
|
||||
if secretKey == "" {
|
||||
return "", errors.New("SECRET_KEY is not set in the environment variables")
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(secretKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
// ValidateJWT validates a given JWT token.
|
||||
func ValidateJWT(tokenString string) (*JWTClaims, error) {
|
||||
loadEnv()
|
||||
secretKey := os.Getenv("SECRET_KEY")
|
||||
if secretKey == "" {
|
||||
return nil, errors.New("SECRET_KEY is not set in the environment variables")
|
||||
}
|
||||
|
||||
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, errors.New("unexpected signing method")
|
||||
}
|
||||
return []byte(secretKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
|
||||
// GenerateClaims creates JWT claims.
|
||||
func GenerateClaims(userID uint) (*JWTClaims , error) {
|
||||
db := database.Db()
|
||||
role_query := Role_repository.RoleQueryRepository{DB: &db}
|
||||
user_query := User_repository.UserQueryRepository{DB: &db}
|
||||
|
||||
user , err := user_query.GetUser(userID)
|
||||
if err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
role , err := role_query.GetRole(user.Role_id)
|
||||
if err != nil {
|
||||
return nil , err
|
||||
}
|
||||
|
||||
cliams := &JWTClaims{
|
||||
ID: user.User_id,
|
||||
Role: role.Name,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
ExpiresAt: time.Now().Add(time.Hour * 2).Unix(),
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
return cliams , nil
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package authentication
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"netina/database"
|
||||
"netina/models"
|
||||
u "netina/queries"
|
||||
user_repository "netina/repositories/user"
|
||||
sms "netina/services"
|
||||
"netina/validation"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func RequestCode(c echo.Context) error {
|
||||
db := database.Db()
|
||||
|
||||
gc := NewGenerateCode(&db)
|
||||
|
||||
phoneNumber := new(models.CreatePhoneNumber)
|
||||
if err := c.Bind(phoneNumber); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
|
||||
}
|
||||
|
||||
if err := validation.ValidateStruct(phoneNumber); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
loginCode ,err := gc.CreateLoginCode(phoneNumber.PhoneNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sms.Sms(phoneNumber.PhoneNumber , loginCode)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func Login(c echo.Context) error {
|
||||
db := database.Db()
|
||||
code := new(models.LoginCode)
|
||||
if err := c.Bind(code); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validation.ValidateStruct(code); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
gc := NewGenerateCode(&db)
|
||||
|
||||
if gc.VerifyLoginCode(code.PhoneNumber , code.Code) == nil {
|
||||
ur := user_repository.UserQueryRepository{DB: &db}
|
||||
userHandller := u.GetUserByPhoneNumberHandler{Repository: ur}
|
||||
user , err := userHandller.Handle(code.PhoneNumber)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusNotFound , "user not found")
|
||||
}
|
||||
|
||||
token , err:= GenerateTokenForUser(user.User_id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusAccepted , token)
|
||||
|
||||
} else {
|
||||
return c.JSON(http.StatusBadRequest , "invalid Request")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package authentication
|
||||
|
||||
func GenerateTokenForUser(userID uint) (string, error) {
|
||||
claims, err := GenerateClaims(userID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
token, err := GenerateJWT(claims)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func ValidateUserToken(tokenString string) (*JWTClaims, error) {
|
||||
claims, err := ValidateJWT(tokenString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return claims, nil
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package authorization
|
||||
|
||||
import (
|
||||
j "netina/services/authentication"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func AdminRole(next echo.HandlerFunc)echo.HandlerFunc{
|
||||
return func(c echo.Context)error{
|
||||
user := c.Get("user").(*j.JWTClaims)
|
||||
if user == nil {
|
||||
return echo.ErrUnauthorized
|
||||
}
|
||||
|
||||
if user.Role != "admin" {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
|
||||
type LicenseService struct {
|
||||
CommandRepo license_repository.LicenseCommandRepository
|
||||
QueryRepo license_repository.LicenseQueryRepository
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"netina/commands"
|
||||
cm "netina/models/commands"
|
||||
"netina/queries"
|
||||
Role_repository "netina/repositories/role"
|
||||
"netina/validation"
|
||||
"strconv"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type RoleService struct {
|
||||
CommandRepo Role_repository.RoleCommandRepository
|
||||
QueryRepo Role_repository.RoleQueryRepository
|
||||
}
|
||||
|
||||
func (s *RoleService) CreateRole(c echo.Context) error {
|
||||
role := new(cm.CreateRoleCommand)
|
||||
if err := c.Bind(role); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
|
||||
}
|
||||
if err := validation.ValidateStruct(role); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
handler := commands.CreateRoleHandler{Repository: s.CommandRepo}
|
||||
if err := handler.Handle(*role); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusCreated, role)
|
||||
}
|
||||
|
||||
func (s *RoleService) GetRole(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid role ID"})
|
||||
}
|
||||
|
||||
handler := queries.GetRoleHandler{Repository: s.QueryRepo}
|
||||
role, err := handler.Handle(uint(id))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, role)
|
||||
}
|
||||
|
||||
func (s *RoleService) UpdateRole(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid role ID"})
|
||||
}
|
||||
|
||||
role := new(cm.UpdateRoleCommand)
|
||||
if err := c.Bind(role); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
|
||||
}
|
||||
if err := validation.ValidateStruct(role); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
handler := commands.UpdateRoleHandler{Repository: s.CommandRepo}
|
||||
updatedRole, err := handler.Handle(uint(id), *role)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, updatedRole)
|
||||
}
|
||||
|
||||
func (s *RoleService) RemoveRole(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid Role ID"})
|
||||
}
|
||||
|
||||
handler := commands.RemoveRoleHandler{Repository: s.CommandRepo}
|
||||
if err := handler.Handle(uint(id)); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kavenegar/kavenegar-go"
|
||||
)
|
||||
func Sms(phoneNumber string , loginCode string) {
|
||||
api := kavenegar.New("65334B6A70303233432B7A6530795A51683134524945742F74397161785568512B794966623245744C2F773D")
|
||||
receptor := phoneNumber
|
||||
template := "verify"
|
||||
token := loginCode
|
||||
params := &kavenegar.VerifyLookupParam{
|
||||
}
|
||||
if res, err := api.Verify.Lookup(receptor, template, token, params); err != nil {
|
||||
switch err := err.(type) {
|
||||
case *kavenegar.APIError:
|
||||
fmt.Println(err.Error())
|
||||
case *kavenegar.HTTPError:
|
||||
fmt.Println(err.Error())
|
||||
default:
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
} else {
|
||||
fmt.Println("MessageID = ", res.MessageID)
|
||||
fmt.Println("Status = ", res.Status)
|
||||
//...
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"netina/commands"
|
||||
"netina/models"
|
||||
cm "netina/models/commands"
|
||||
"netina/queries"
|
||||
User_repository "netina/repositories/user"
|
||||
"netina/validation"
|
||||
"strconv"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
CommandRepo User_repository.UserCommandRepository
|
||||
QueryRepo User_repository.UserQueryRepository
|
||||
}
|
||||
|
||||
func (s *UserService) CreateUser(c echo.Context) error {
|
||||
user := new(cm.CreateUserCommand)
|
||||
if err := c.Bind(user); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
|
||||
}
|
||||
if err := validation.ValidateStruct(user); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
handler := commands.CreateUserHandler{Repository: s.CommandRepo}
|
||||
if err := handler.Handle(*user); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusCreated, user)
|
||||
}
|
||||
|
||||
func (s *UserService) GetUser(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid User ID"})
|
||||
}
|
||||
|
||||
handler := queries.GetUserByIdHandler{Repository: s.QueryRepo}
|
||||
User, err := handler.Handle(uint(id))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, User)
|
||||
}
|
||||
|
||||
|
||||
func (s *UserService) GetUserByPhoneNumber(c echo.Context) error {
|
||||
number := new(models.CreatePhoneNumber)
|
||||
if err := c.Bind(number); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid phone number"})
|
||||
}
|
||||
|
||||
handler := queries.GetUserByPhoneNumberHandler{Repository: s.QueryRepo}
|
||||
user , err := handler.Handle(number.PhoneNumber)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK , user)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (s *UserService) UpdateUser(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid User ID"})
|
||||
}
|
||||
|
||||
User := new(cm.UpdateUserCommand)
|
||||
if err := c.Bind(User); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
|
||||
}
|
||||
if err := validation.ValidateStruct(User); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
handler := commands.UpdateUserHandler{Repository: s.CommandRepo}
|
||||
updatedUser, err := handler.Handle(uint(id), *User)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, updatedUser)
|
||||
}
|
||||
|
||||
func (s *UserService) RemoveUser(c echo.Context) error {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid User ID"})
|
||||
}
|
||||
|
||||
handler := commands.RemoveUserHandler{Repository: s.CommandRepo}
|
||||
if err := handler.Handle(uint(id)); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
Loading…
Reference in New Issue