Compare commits

...

5 Commits

Author SHA1 Message Date
nima c0b3a30847 bug fixes and some minor changes in models 2024-07-13 16:49:16 +03:30
nima a0e40b3a8f upload file service added 2024-07-13 16:48:09 +03:30
nima 2a1de207df update panel service added 2024-07-13 16:47:45 +03:30
nima 5f9a2309c1 expire rout added 2024-07-13 16:46:46 +03:30
nima 4694b12e1b jwt model added 2024-07-13 16:41:11 +03:30
39 changed files with 1074 additions and 96 deletions

View File

@ -4,6 +4,7 @@ import (
m "netina/models"
c "netina/models/commands"
l "netina/repositories/license"
"netina/validation"
"time"
)
@ -14,16 +15,20 @@ type CreateLicenseHandler struct {
}
func(r *CreateLicenseHandler) Handle (command c.CreateLicenseCommand) error {
func(r *CreateLicenseHandler) Handle (command c.CreateLicenseCommand , modified_by string) error {
if err := validation.ValidateStruct(command); err != nil {
return err
}
license := &m.License{
Plan_id: command.Plan_id,
Period: command.Period,
Created_at: time.Now(),
Modified_by: command.Modified_by,
Modified_by: modified_by,
NumberOfRenewals: 0,
ExpireDate: command.ExpireDate,
}
return r.Repository.CreateLicense(license)
@ -35,7 +40,7 @@ type UpdateLicenseHandler struct {
}
func (r *UpdateLicenseHandler) Handle (id uint , command c.UpdateLicenseCommand) (*m.License , error) {
func (r *UpdateLicenseHandler) Handle (id uint , command c.UpdateLicenseCommand , modified_by string) (*m.License , error) {
if err := validation.ValidateStruct(command); err != nil {
return nil , err
@ -43,9 +48,10 @@ func (r *UpdateLicenseHandler) Handle (id uint , command c.UpdateLicenseCommand)
license := &m.License{
Plan_id: command.Plan_id,
Period: command.Period,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Modified_at: time.Now(),
ExpireDate: command.ExpireDate,
NumberOfRenewals: command.NumberOfRenewals,
}
return r.Repository.UpdateLicense(id , license)

View File

@ -13,7 +13,7 @@ type CreateOwnerHandler struct{
Repository o.OwnerCommandRepository
}
func (r *CreateOwnerHandler) Handle(command c.CreateOwnerCommand) error {
func (r *CreateOwnerHandler) Handle(command c.CreateOwnerCommand , modified_by string) error {
if err := validation.ValidateStruct(command); err != nil {
return err
}
@ -23,7 +23,7 @@ func (r *CreateOwnerHandler) Handle(command c.CreateOwnerCommand) error {
LastName: command.LastName,
NationalCode: command.NationalCode,
Created_at: time.Now(),
Modified_by: command.Modified_by,
Modified_by: modified_by,
}
return r.Repository.CreateOwner(owner)
@ -35,7 +35,7 @@ type UpdateOwnerHandler struct {
}
func (r *UpdateOwnerHandler) Handle(id uint , command c.UpdateOwnerCommand)(*m.Owner , error) {
func (r *UpdateOwnerHandler) Handle(id uint , command c.UpdateOwnerCommand , modified_by string)(*m.Owner , error) {
if err := validation.ValidateStruct(command); err != nil {
return nil , err
@ -46,7 +46,7 @@ func (r *UpdateOwnerHandler) Handle(id uint , command c.UpdateOwnerCommand)(*m.O
FirstName: command.FirstName,
LastName: command.LastName,
NationalCode: command.NationalCode,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Modified_at: time.Now(),
}

View File

@ -14,7 +14,7 @@ type CreatePlanHandler struct {
func (r *CreatePlanHandler) Handle(command c.CreatePlanCommand) error {
func (r *CreatePlanHandler) Handle(command c.CreatePlanCommand , modified_by string) error {
if err := validation.ValidateStruct(command); err != nil {
return err
@ -22,11 +22,11 @@ func (r *CreatePlanHandler) Handle(command c.CreatePlanCommand) error {
plan := &m.Plan{
Price: command.Price,
Priod: command.Priod,
Partnership: command.Partnership,
Period: command.Period,
Partnership: *command.Partnership,
PercentageOfOwner: command.PercentageOfOwner,
Created_at: time.Now(),
Modified_by: command.Modified_by,
Modified_by: modified_by,
}
return r.Repository.CreatePlan(plan)
@ -38,17 +38,18 @@ type UpdatePlanHandler struct {
}
func (r *UpdatePlanHandler) Handle (id uint , command c.UpdatePlanCommand)(*m.Plan , error) {
func (r *UpdatePlanHandler) Handle (id uint , command c.UpdatePlanCommand , modified_by string)(*m.Plan , error) {
if err := validation.ValidateStruct(command); err != nil {
return nil , err
}
plan := &m.Plan{
Price: command.Price,
Priod: command.Priod,
Partnership: command.Partnership,
Period: command.Period,
Partnership: *command.Partnership,
PercentageOfOwner: command.PercentageOfOwner,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Modified_at: time.Now(),
}

View File

@ -14,7 +14,7 @@ type CreateRoleHandler struct {
func (r *CreateRoleHandler) Handle(command c.CreateRoleCommand) error {
func (r *CreateRoleHandler) Handle(command c.CreateRoleCommand , modified_by string) error {
if err := validation.ValidateStruct(command); err != nil {
return err
@ -23,7 +23,7 @@ func (r *CreateRoleHandler) Handle(command c.CreateRoleCommand) error {
role := &m.Role{
Name: command.Name,
Created_at: time.Now(),
Modified_by: command.Modified_by ,
Modified_by: modified_by ,
}
return r.Repository.CreateRole(role)
@ -35,14 +35,14 @@ type UpdateRoleHandler struct {
}
func (r *UpdateRoleHandler) Handle (id uint , command c.UpdateRoleCommand)(*m.Role , error) {
func (r *UpdateRoleHandler) Handle (id uint , command c.UpdateRoleCommand , modified_by string)(*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_by: modified_by,
Modified_at: time.Now(),
}

View File

@ -14,7 +14,7 @@ type CreateStoreHandler struct {
}
func (r *CreateStoreHandler) Handle (command c.CreateStoreCommand)error {
func (r *CreateStoreHandler) Handle (command c.CreateStoreCommand , modified_by string)error {
if err := validation.ValidateStruct(command); err != nil {
return err
@ -30,10 +30,23 @@ func (r *CreateStoreHandler) Handle (command c.CreateStoreCommand)error {
AdminPanelAddress: command.AdminPanelAddress,
StorageAddress: command.StorageAddress,
License_id: command.License_id,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Created_at: time.Now(),
StorageApiKey: command.StorageApiKey,
StorageSecret: command.StorageSecret,
StorageName: command.StorageName,
}
// baseDir := "../uploads"
// dirName := command.Name
// targetDir := filepath.Join(baseDir , dirName)
// err := os.MkdirAll(targetDir, 0755)
// if err != nil {
// return err
// }
return r.Repository.CreateStore(store)
}
@ -45,7 +58,7 @@ type UpdateStoreHandler struct {
}
func (r *UpdateStoreHandler) Handle (id uint ,command c.UpdateStoreCommand)(*m.Store , error) {
func (r *UpdateStoreHandler) Handle (id uint ,command c.UpdateStoreCommand , modified_by string)(*m.Store , error) {
if err := validation.ValidateStruct(command); err != nil {
return nil,err
@ -62,9 +75,11 @@ func (r *UpdateStoreHandler) Handle (id uint ,command c.UpdateStoreCommand)(*m.S
ApiAddress: command.ApiAddress,
AdminPanelAddress: command.AdminPanelAddress,
StorageAddress: command.StorageAddress,
License_id: command.License_id,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Modified_at: time.Now(),
StorageName: command.StorageName,
StorageApiKey: command.StorageApiKey,
StorageSecret: command.StorageSecret,
}

View File

@ -14,7 +14,7 @@ type CreateUserHandler struct {
func (r *CreateUserHandler) Handle(command c.CreateUserCommand) error {
func (r *CreateUserHandler) Handle(command c.CreateUserCommand , modified_by string) error {
if err := validation.ValidateStruct(command); err != nil {
return err
@ -26,7 +26,7 @@ func (r *CreateUserHandler) Handle(command c.CreateUserCommand) error {
PhoneNumber: command.PhoneNumber,
Role_id: command.Role_id,
Created_at: time.Now(),
Modified_by: command.Modified_by,
Modified_by: modified_by,
}
return r.Repository.CreateUser(User)
@ -38,7 +38,7 @@ type UpdateUserHandler struct {
}
func (r *UpdateUserHandler) Handle (id uint , command c.UpdateUserCommand)(*m.User , error) {
func (r *UpdateUserHandler) Handle (id uint , command c.UpdateUserCommand , modified_by string)(*m.User , error) {
if err := validation.ValidateStruct(command); err != nil {
return nil , err
}
@ -47,7 +47,7 @@ func (r *UpdateUserHandler) Handle (id uint , command c.UpdateUserCommand)(*m.Us
Name: command.Name,
PhoneNumber: command.PhoneNumber,
Role_id: command.Role_id,
Modified_by: command.Modified_by,
Modified_by: modified_by,
Modified_at: time.Now(),
}

View File

@ -2,4 +2,9 @@ DB_HOST="localhost"
DB_PORT=5433
DB_USER="postgres"
DB_PASSWORD="1"
DB_NAME="netina"
DB_NAME="netina"
SECRET_KEY = "Cw7$?fm7Or[*.&V+-{T6uVZ`}Wdx=g"
ADMIN_NUMBER = "09356684212"

32
go.mod
View File

@ -9,6 +9,37 @@ require (
)
require (
github.com/aws/aws-sdk-go v1.54.9 // indirect
github.com/casbin/casbin/v2 v2.96.0 // indirect
github.com/casbin/gorm-adapter/v2 v2.1.0 // indirect
github.com/casbin/gorm-adapter/v3 v3.25.0 // indirect
github.com/casbin/govaluate v1.1.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/glebarez/go-sqlite v1.20.3 // indirect
github.com/glebarez/sqlite v1.7.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jinzhu/gorm v1.9.12 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kavenegar/kavenegar-go v0.0.0-20240205151018-77039f51467d // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/microsoft/go-mssqldb v1.6.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 // indirect
golang.org/x/time v0.5.0 // indirect
gorm.io/driver/mysql v1.5.6 // indirect
gorm.io/driver/sqlserver v1.5.3 // indirect
gorm.io/plugin/dbresolver v1.3.0 // indirect
modernc.org/libc v1.22.2 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.20.3 // indirect
)
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@ -18,6 +49,7 @@ require (
github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/echo/v4 v4.12.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.4.0 // indirect

180
go.sum
View File

@ -1,73 +1,253 @@
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/aws/aws-sdk-go v1.54.9 h1:e0Czh9AhrCVPuyaIUnibYmih3cYexJKlqlHSJ2eMKbI=
github.com/aws/aws-sdk-go v1.54.9/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/casbin/casbin/v2 v2.2.2/go.mod h1:XXtYGrs/0zlOsJMeRteEdVi/FsB0ph7KgNfjoCoJUD8=
github.com/casbin/casbin/v2 v2.96.0 h1:uHEOYAk3vmh1xREUeCnuD/crJuokH5d/wd2PSCN3BSk=
github.com/casbin/casbin/v2 v2.96.0/go.mod h1:jX8uoN4veP85O/n2674r2qtfSXI6myvxW85f6TH50fw=
github.com/casbin/gorm-adapter/v2 v2.1.0 h1:wBimcRJ4V/Dq5o95OIBzeM6vvxNfjzCV235biWoSO4I=
github.com/casbin/gorm-adapter/v2 v2.1.0/go.mod h1:Sy5LYivXiUVRvPZFasa6puLle0RaxNpV2TJ7yzlQkZc=
github.com/casbin/gorm-adapter/v3 v3.25.0 h1:XQkat6m7RvAiEkX4VEh+nUOq1559zbrfVwd8ip8wlCI=
github.com/casbin/gorm-adapter/v3 v3.25.0/go.mod h1:aftWi0cla0CC1bHQVrSFzBcX/98IFK28AvuPppCQgTs=
github.com/casbin/govaluate v1.1.0 h1:6xdCWIpE9CwHdZhlVQW+froUrCsjb6/ZYNcXODfLT+E=
github.com/casbin/govaluate v1.1.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
github.com/glebarez/sqlite v1.7.0 h1:A7Xj/KN2Lvie4Z4rrgQHY8MsbebX3NyWsL3n2i82MVI=
github.com/glebarez/sqlite v1.7.0/go.mod h1:PkeevrRlF/1BhQBCnzcMWzgrIk7IOop+qS2jUYLfHhk=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kavenegar/kavenegar-go v0.0.0-20240205151018-77039f51467d h1:5yPyBSS28Nojbr7pAkiXADGj6VpTXx73o6SsprKbSoo=
github.com/kavenegar/kavenegar-go v0.0.0-20240205151018-77039f51467d/go.mod h1:CRhvvr4KNAyrg+ewrutOf+/QoHs7lztSoLjp+GqhYlA=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 h1:VstopitMQi3hZP0fzvnsLmzXZdQGc4bEcgu24cp+d4M=
github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U=
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0=
gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00=
gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/plugin/dbresolver v1.3.0 h1:uFDX3bIuH9Lhj5LY2oyqR/bU6pqWuDgas35NAPF4X3M=
gorm.io/plugin/dbresolver v1.3.0/go.mod h1:Pr7p5+JFlgDaiM6sOrli5olekJD16YRunMyA2S7ZfKk=
modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0=
modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs=
modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A=

View File

@ -6,6 +6,7 @@ import (
"netina/router"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
@ -14,13 +15,17 @@ import (
func main(){
db.Create_tables()
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
i.Init()
router.LoginRoutes(e)
router.UploadFile(e)
router.OwnerRoutes(e)
router.LicenseRoutes(e)
router.PlanRoutes(e)
router.StoreRoutes(e)
router.UserRoutes(e)
router.RoleRoutes(e)
router.PanelRoutes(e)
e.Logger.Fatal(e.Start(":8800"))
}

View File

@ -11,7 +11,10 @@ type Store struct {
PhoneNumber string
WebAddress string
ApiAddress string
StorageName string
StorageAddress string
StorageApiKey string
StorageSecret string
AdminPanelAddress string
License_id uint
License License `gorm:"references:License_id"`

View File

@ -3,15 +3,12 @@ package models
import "time"
type CreateLicenseCommand struct {
Plan_id uint `validate:"required"`
Period time.Time `validate:"required"`
Modified_by string `validate:"required"`
Plan_id uint `validate:"required"`
ExpireDate time.Time
}
type UpdateLicenseCommand struct {
Plan_id uint `validate:"required"`
Period time.Time `validate:"required"`
Modified_by string `validate:"required"`
Plan_id uint `validate:"required"`
ExpireDate time.Time
NumberOfRenewals uint
}

View File

@ -5,7 +5,6 @@ type CreateOwnerCommand struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
NationalCode string `validate:"required"`
Modified_by string `validate:"required"`
}
type UpdateOwnerCommand struct {
@ -13,5 +12,4 @@ type UpdateOwnerCommand struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
NationalCode string `validate:"required"`
Modified_by string `validate:"required"`
}

View File

@ -1,21 +1,15 @@
package models
import "time"
type CreatePlanCommand struct {
Price uint `validate:"required"`
Priod time.Time `validate:"required"`
Partnership bool `validate:"required"`
PercentageOfOwner uint `validate:"required"`
Modified_by string `validate:"required"`
Price uint `validate:"required"`
Period uint `validate:"required"`
Partnership *bool `json:"partnership" validate:"required"`
PercentageOfOwner uint `validate:"required"`
}
type UpdatePlanCommand struct {
Price uint `validate:"required"`
Priod time.Time `validate:"required"`
Partnership bool `validate:"required"`
PercentageOfOwner uint `validate:"required"`
Modified_by string `validate:"required"`
Price uint `validate:"required"`
Period uint `validate:"required"`
Partnership *bool `json:"partnership" validate:"required"`
PercentageOfOwner uint `validate:"required"`
}

View File

@ -1,11 +1,9 @@
package models
type CreateRoleCommand struct {
Name string `validate:"required"`
Modified_by string `validate:"required"`
Name string `validate:"required"`
}
type UpdateRoleCommand struct {
Name string `validate:"required"`
Modified_by string `validate:"required"`
Name string `validate:"required"`
}

View File

@ -7,10 +7,12 @@ type CreateStoreCommand struct {
PhoneNumber string `validate:"required"`
WebAddress string `validate:"required"`
ApiAddress string `validate:"required"`
StorageName string `validate:"required"`
StorageAddress string `validate:"required"`
StorageApiKey string `validate:"required"`
StorageSecret string `validate:"required"`
AdminPanelAddress string `validate:"required"`
License_id uint `validate:"required"`
Modified_by string `validate:"required"`
}
type UpdateStoreCommand struct {
@ -20,8 +22,10 @@ type UpdateStoreCommand struct {
PhoneNumber string `validate:"required"`
WebAddress string `validate:"required"`
ApiAddress string `validate:"required"`
StorageName string `validate:"required"`
StorageApiKey string `validate:"required"`
StorageSecret string `validate:"required"`
StorageAddress string `validate:"required"`
AdminPanelAddress string `validate:"required"`
License_id uint `validate:"required"`
Modified_by string `validate:"required"`
}

View File

@ -4,12 +4,10 @@ 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"`
}

10
models/jwt.go 100644
View File

@ -0,0 +1,10 @@
package models
import "github.com/dgrijalva/jwt-go"
// JWTClaims defines the structure of JWT claims.
type JWTClaims struct {
ID uint `json:"id"`
Role string `json:"role"`
jwt.StandardClaims
}

View File

@ -6,7 +6,8 @@ type License struct {
License_id uint `gorm:"primaryKey"`
Plan_id uint
Plan Plan `gorm:"references:Plan_id"`
Period time.Time
ExpireDate time.Time
NumberOfRenewals uint
Created_at time.Time
Modified_at time.Time
Modified_by string

View File

@ -5,7 +5,7 @@ import "time"
type Plan struct {
Plan_id uint `gorm:"primaryKey"`
Price uint
Priod time.Time
Period uint
Partnership bool
PercentageOfOwner uint
Created_at time.Time

View File

@ -34,9 +34,12 @@ func (r *LicenseCommandRepository) UpdateLicense(id uint , license *models.Licen
return nil , err
}
temp.Period = license.Period
temp.Modified_at = license.Modified_at
temp.Modified_by = license.Modified_by
temp.ExpireDate = license.ExpireDate
temp.Plan_id = license.Plan_id
temp.NumberOfRenewals = license.NumberOfRenewals
if err := r.DB.Save(&temp).Error; err != nil {

View File

@ -39,6 +39,7 @@ func (r *PlanCommandRepository) UpdatePlan(id uint , plan *models.Plan)(*models.
temp.Modified_by = plan.Modified_by
temp.PercentageOfOwner = plan.PercentageOfOwner
temp.Price = plan.Price
temp.Period = plan.Period
if err := r.DB.Save(&temp).Error; err != nil {
return nil , err

View File

@ -34,6 +34,7 @@ func (r *StoreCommandRepository) UpdateStore(id uint , store *models.Store)(*mod
return nil , err
}
temp.Owner_id = store.Owner_id
temp.Address = store.Address
temp.PhoneNumber = store.PhoneNumber
temp.AdminPanelAddress = store.AdminPanelAddress
@ -43,6 +44,10 @@ func (r *StoreCommandRepository) UpdateStore(id uint , store *models.Store)(*mod
temp.StorageAddress = store.StorageAddress
temp.Name = store.Name
temp.WebAddress = store.WebAddress
temp.StorageApiKey = store.StorageApiKey
temp.StorageSecret = store.StorageSecret
temp.StorageName = store.StorageName
if err := r.DB.Save(&temp).Error; err != nil {

View File

@ -10,6 +10,7 @@ import (
store_repository "netina/repositories/store"
user_repository "netina/repositories/user"
"netina/services"
auth "netina/services/authentication"
a "netina/services/authorization"
@ -18,6 +19,9 @@ import (
func LoginRoutes(e *echo.Echo) {
login := e.Group("/login")
login.POST("/phonenumber" , auth.RequestCode)
@ -25,6 +29,20 @@ func LoginRoutes(e *echo.Echo) {
}
func UploadFile(e *echo.Echo){
upload := e.Group("/upload")
upload.Use(middlewares.JWTMiddleware)
upload.POST("/", services.Upload , a.AdminRole )
}
func PanelRoutes(e *echo.Echo){
panel := e.Group("/panel")
panel.Use(middlewares.JWTMiddleware)
panel.GET("/" , services.UpdatePanel , a.AdminRole)
}
func UserRoutes(e *echo.Echo){
db := database.Db()
@ -111,6 +129,7 @@ func StoreRoutes(e *echo.Echo) {
store.POST("/",storeService.CreateStore,a.AdminRole)
store.GET("/:id" , storeService.GetStore)
store.GET("/owner/:id" , storeService.GetStoresList)
store.GET("/expiredate/:id" , services.ExpireDate , a.AdminRole)
store.PUT("/:id" , storeService.UpdateStore,a.AdminRole)
store.DELETE("/:id" , storeService.RemoveStore,a.AdminRole)
}

View File

@ -8,17 +8,12 @@ import (
"os"
"time"
"netina/models"
"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")
@ -28,7 +23,7 @@ func loadEnv() {
}
// GenerateJWT generates a new JWT token.
func GenerateJWT(claims *JWTClaims) (string, error) {
func GenerateJWT(claims *models.JWTClaims) (string, error) {
loadEnv()
secretKey := os.Getenv("SECRET_KEY")
if secretKey == "" {
@ -45,14 +40,14 @@ func GenerateJWT(claims *JWTClaims) (string, error) {
}
// ValidateJWT validates a given JWT token.
func ValidateJWT(tokenString string) (*JWTClaims, error) {
func ValidateJWT(tokenString string) (*models.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) {
token, err := jwt.ParseWithClaims(tokenString, &models.JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("unexpected signing method")
}
@ -62,7 +57,7 @@ func ValidateJWT(tokenString string) (*JWTClaims, error) {
return nil, err
}
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
if claims, ok := token.Claims.(*models.JWTClaims); ok && token.Valid {
return claims, nil
}
@ -70,7 +65,7 @@ func ValidateJWT(tokenString string) (*JWTClaims, error) {
}
// GenerateClaims creates JWT claims.
func GenerateClaims(userID uint) (*JWTClaims , error) {
func GenerateClaims(userID uint) (*models.JWTClaims , error) {
db := database.Db()
role_query := Role_repository.RoleQueryRepository{DB: &db}
user_query := User_repository.UserQueryRepository{DB: &db}
@ -85,7 +80,7 @@ func GenerateClaims(userID uint) (*JWTClaims , error) {
return nil , err
}
cliams := &JWTClaims{
cliams := &models.JWTClaims{
ID: user.User_id,
Role: role.Name,
StandardClaims: jwt.StandardClaims{

View File

@ -12,6 +12,7 @@ import (
"github.com/labstack/echo/v4"
)
func RequestCode(c echo.Context) error {
db := database.Db()

View File

@ -1,5 +1,7 @@
package authentication
import "netina/models"
func GenerateTokenForUser(userID uint) (string, error) {
claims, err := GenerateClaims(userID)
if err != nil {
@ -12,7 +14,7 @@ func GenerateTokenForUser(userID uint) (string, error) {
return token, nil
}
func ValidateUserToken(tokenString string) (*JWTClaims, error) {
func ValidateUserToken(tokenString string) (*models.JWTClaims, error) {
claims, err := ValidateJWT(tokenString)
if err != nil {
return nil, err

View File

@ -0,0 +1,89 @@
package authorization
// import (
// "netina/database"
// "github.com/casbin/casbin/v2"
// gormadapter "github.com/casbin/gorm-adapter/v3"
// )
// func enf(){
// db := database.Db()
// adapter, err := gormadapter.NewAdapterByDB(db)
// if err != nil {
// panic("failed to create adapter")
// }
// // Define Casbin model in code
// modelText := `
// [request_definition]
// r = sub, obj, act
// [policy_definition]
// p = sub, obj, act
// [role_definition]
// g = _, _
// [policy_effect]
// e = some(where (p.eft == allow))
// [matchers]
// m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
// `
// // Initialize Casbin enforcer with model text and adapter
// m := casbin.NewEnforceContext(modelText)
// enforcer, err := casbin.NewEnforcer(m, adapter)
// if err != nil {
// panic("failed to create enforcer")
// }
// // Load policies from DB
// enforcer.LoadPolicy()
// // Define policies
// definePolicies(enforcer)
// // Save policies to DB
// enforcer.SavePolicy()
// }
// // Define policies for admin and user roles
// func definePolicies(enforcer *casbin.Enforcer) {
// // Admin policies (full access)
// enforcer.AddPolicy("admin", "/user/*", "GET")
// enforcer.AddPolicy("admin", "/user/*", "POST")
// enforcer.AddPolicy("admin", "/user/*", "PUT")
// enforcer.AddPolicy("admin", "/user/*", "DELETE")
// enforcer.AddPolicy("admin", "/owner/*", "GET")
// enforcer.AddPolicy("admin", "/owner/*", "POST")
// enforcer.AddPolicy("admin", "/owner/*", "PUT")
// enforcer.AddPolicy("admin", "/owner/*", "DELETE")
// enforcer.AddPolicy("admin", "/license/*", "GET")
// enforcer.AddPolicy("admin", "/license/*", "POST")
// enforcer.AddPolicy("admin", "/license/*", "PUT")
// enforcer.AddPolicy("admin", "/license/*", "DELETE")
// enforcer.AddPolicy("admin", "/plan/*", "GET")
// enforcer.AddPolicy("admin", "/plan/*", "POST")
// enforcer.AddPolicy("admin", "/plan/*", "PUT")
// enforcer.AddPolicy("admin", "/plan/*", "DELETE")
// enforcer.AddPolicy("admin", "/store/*", "GET")
// enforcer.AddPolicy("admin", "/store/*", "POST")
// enforcer.AddPolicy("admin", "/store/*", "PUT")
// enforcer.AddPolicy("admin", "/store/*", "DELETE")
// // User policies (limited access)
// enforcer.AddPolicy("user", "/owner/*", "GET")
// enforcer.AddPolicy("user", "/store/*", "GET")
// enforcer.AddPolicy("user", "/plan/*", "GET")
// enforcer.AddPolicy("user", "/license/*", "GET")
// }

View File

@ -1,7 +1,7 @@
package authorization
import (
j "netina/services/authentication"
"netina/models"
"github.com/labstack/echo/v4"
)
@ -10,7 +10,7 @@ import (
func AdminRole(next echo.HandlerFunc)echo.HandlerFunc{
return func(c echo.Context)error{
user := c.Get("user").(*j.JWTClaims)
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}

65
services/expire.go 100644
View File

@ -0,0 +1,65 @@
package services
import (
"net/http"
"netina/database"
license_repository "netina/repositories/license"
store_repository "netina/repositories/store"
"strconv"
"time"
"github.com/labstack/echo/v4"
)
func ExpireDate(c echo.Context) error {
db := database.Db()
storeQuery := store_repository.StoreQueryRepository{DB: &db}
licenseQuery := license_repository.LicenseQueryRepository{DB: &db}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid store ID"})
}
store , err := storeQuery.GetStore(uint(id))
if err != nil {
return err
}
license , err := licenseQuery.GetLicense(store.License_id)
if err != nil {
return err
}
if time.Now().After(license.ExpireDate) {
return c.JSON(http.StatusOK , map[string]string{"error": "license expired"})
} else {
remainingTime := time.Until(license.ExpireDate)
secondsRemaining := remainingTime.Seconds()
minutesRemaining := remainingTime.Minutes()
hoursRemaining := remainingTime.Hours()
daysRemaining := hoursRemaining/24
secondsRemainingStr := strconv.FormatFloat(secondsRemaining, 'f', -1, 64)
minutesRemainingStr := strconv.FormatFloat(minutesRemaining, 'f', -1, 64)
hoursRemainingStr := strconv.FormatFloat(hoursRemaining, 'f', -1, 64)
daysRemainingStr := strconv.FormatFloat(daysRemaining, 'f', -1, 64)
timeMap := map[string]string{
"secondsRemaining": secondsRemainingStr,
"minutesRemaining": minutesRemainingStr,
"hoursRemaining": hoursRemainingStr,
"daysRemaining": daysRemainingStr,
}
return c.JSON(http.StatusOK , timeMap )
}
}

View File

@ -3,11 +3,13 @@ package services
import (
"net/http"
"netina/commands"
"netina/models"
cm "netina/models/commands"
"netina/queries"
license_repository "netina/repositories/license"
"netina/validation"
"strconv"
"time"
"github.com/labstack/echo/v4"
)
@ -19,6 +21,16 @@ type LicenseService struct {
}
func (s *LicenseService) CreateLicense(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
license := new(cm.CreateLicenseCommand)
if err := c.Bind(license); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
@ -27,8 +39,22 @@ func (s *LicenseService) CreateLicense(c echo.Context) error {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
plan , err := FindPlan(license.Plan_id)
if err != nil {
return err
}
period := plan.Period
// convert nano seconds to days
expireDate := time.Now().Add((time.Duration(period)*1000000000*3600*24))
license.ExpireDate = expireDate
handler := commands.CreateLicenseHandler{Repository: s.CommandRepo}
if err := handler.Handle(*license); err != nil {
if err := handler.Handle(*license , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -51,6 +77,16 @@ func (s *LicenseService) GetLicense(c echo.Context) error {
}
func (s *LicenseService) UpdateLicense(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid license ID"})
@ -60,12 +96,37 @@ func (s *LicenseService) UpdateLicense(c echo.Context) error {
if err := c.Bind(license); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
}
handle := queries.GetLicenseHandler{Repository: s.QueryRepo}
ls, err := handle.Handle(uint(id))
if err != nil {
return c.JSON(http.StatusNotFound, map[string]string{"error": err.Error()})
}
numberOfRenewals := ls.NumberOfRenewals + 1
license.NumberOfRenewals = numberOfRenewals
plan , err := FindPlan(license.Plan_id)
if err != nil {
return err
}
period := plan.Period
// convert nano seconds to days
expireDate := ls.ExpireDate.Add((time.Duration(period)*1000000000*3600*24))
license.ExpireDate = expireDate
if err := validation.ValidateStruct(license); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
handler := commands.UpdateLicenseHandler{Repository: s.CommandRepo}
updatedLicense, err := handler.Handle(uint(id), *license)
updatedLicense, err := handler.Handle(uint(id), *license , u.Name)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}

View File

@ -3,6 +3,8 @@ package services
import (
"net/http"
"netina/commands"
"netina/database"
"netina/models"
cm "netina/models/commands"
"netina/queries"
owner_repository "netina/repositories/owner"
@ -18,6 +20,16 @@ type OwnerService struct {
}
func (s *OwnerService) CreateOwner(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
owner := new(cm.CreateOwnerCommand)
if err := c.Bind(owner); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
@ -27,7 +39,7 @@ func (s *OwnerService) CreateOwner(c echo.Context) error {
}
handler := commands.CreateOwnerHandler{Repository: s.CommandRepo}
if err := handler.Handle(*owner); err != nil {
if err := handler.Handle(*owner , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -50,6 +62,16 @@ func (s *OwnerService) GetOwner(c echo.Context) error {
}
func (s *OwnerService) UpdateOwner(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid owner ID"})
@ -64,7 +86,7 @@ func (s *OwnerService) UpdateOwner(c echo.Context) error {
}
handler := commands.UpdateOwnerHandler{Repository: s.CommandRepo}
if _, err := handler.Handle(uint(id), *owner); err != nil {
if _, err := handler.Handle(uint(id), *owner , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -84,3 +106,17 @@ func (s *OwnerService) RemoveOwner(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
func FindOwner(id uint) (*models.Owner , error) {
db := database.Db()
var owner models.Owner
if err := db.Where("is_removed = ?" , false).Where("owner_id = ?" , id).First(&owner).Error; err != nil {
return nil , err
}
return &owner , nil
}

273
services/panel.go 100644
View File

@ -0,0 +1,273 @@
package services
import (
"archive/zip"
"bytes"
"fmt"
"io"
"io/ioutil"
"netina/database"
"netina/models"
"os"
"path/filepath"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/labstack/echo/v4"
)
// ExtractZip extracts a zip file to a specified destination directory
func extractZip(zipPath string, destDir string) ([]string, error) {
r, err := zip.OpenReader(zipPath)
if err != nil {
return nil, err
}
defer r.Close()
var extractedFiles []string
for _, f := range r.File {
fPath := filepath.Join(destDir, f.Name)
if !strings.HasPrefix(fPath, filepath.Clean(destDir)+string(os.PathSeparator)) {
return nil, fmt.Errorf("illegal file path: %s", fPath)
}
extractedFiles = append(extractedFiles, fPath)
if f.FileInfo().IsDir() {
os.MkdirAll(fPath, os.ModePerm)
continue
}
if err := os.MkdirAll(filepath.Dir(fPath), os.ModePerm); err != nil {
return nil, err
}
dstFile, err := os.OpenFile(fPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return nil, err
}
defer dstFile.Close()
srcFile, err := f.Open()
if err != nil {
return nil, err
}
defer srcFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return nil, err
}
}
return extractedFiles, nil
}
func UpdatePanel(c echo.Context) error{
db := database.Db()
var stores []models.Store
if err := db.Where("is_removed = ?" , false).Find(&stores).Error;err != nil {
return err
}
var sess []session.Session
for _ , store := range stores {
ses , err := session.NewSession(&aws.Config{
Credentials: credentials.NewStaticCredentials(store.StorageApiKey , store.StorageSecret , ""),
Region: aws.String("ir-thr-at1"),
Endpoint: aws.String(store.StorageAddress),
})
if err != nil {
return err
}
sess = append(sess, *ses)
}
var svcs []s3.S3
for _ , i := range sess{
svc := s3.New(&i)
svcs = append(svcs, *svc)
}
for i:=0;i<len(svcs);i++ {
_ , err := svcs[i].HeadBucket(&s3.HeadBucketInput{
Bucket: aws.String(stores[i].StorageName),
})
if err != nil {
return err
}
}
// Track cleaned storages
cleanedStorages := make(map[string]bool)
for i := 0;i<len(svcs);i++ {
if !cleanedStorages[stores[i].StorageName] {
if err := deleteAllObjects(&svcs[i] , stores[i].StorageName); err != nil {
return err
}
cleanedStorages[stores[i].StorageName] = true
}
}
dir := "./uploads"
destDir := "extractedFiles"
// Find the ZIP file in the directory
files, err := os.ReadDir(dir)
if err != nil {
return err
}
var zipFilePath string
for _, file := range files {
if !file.IsDir() && strings.HasSuffix(file.Name(), ".zip") {
zipFilePath = filepath.Join(dir, file.Name())
break
}
}
if zipFilePath == "" {
fmt.Println("No ZIP file found in the directory")
return nil
}
// Extract the ZIP file
extractedFiles, err := extractZip(zipFilePath, destDir)
if err != nil {
return nil
}
// Upload extracted files to Arvan Cloud
for _, filePath := range extractedFiles {
key := filepath.Base(filePath)
for i := 0 ; i < len(stores) ; i++ {
err := uploadToArvanCloud(&sess[i] , stores[i].StorageName , filePath , key)
if err != nil {
return err
}
fmt.Printf("Successfully uploaded %s to Arvan Cloud , storage %s \n", filePath , stores[i].StorageAddress)
}
}
removeContents(dir)
removeContents("./extractedFiles")
return nil
}
func uploadToArvanCloud(sess *session.Session , bucket string , filePath string , key string)error{
file, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
uploder := s3manager.NewUploader(sess)
_,err = uploder.Upload(&s3manager.UploadInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: bytes.NewReader(file),
})
if err != nil {
return err
}
return nil
}
func removeContents(dir string) error {
// Read the directory contents
contents, err := ioutil.ReadDir(dir)
if err != nil {
return fmt.Errorf("failed to read directory: %w", err)
}
// Iterate through each item in the directory
for _, item := range contents {
// Construct the full path of the item
itemPath := filepath.Join(dir, item.Name())
// Remove the item (file or directory)
err = os.RemoveAll(itemPath)
if err != nil {
return fmt.Errorf("failed to remove %s: %w", itemPath, err)
}
}
return nil
}
func deleteAllObjects(svc *s3.S3, bucket string) error {
listObjectsInput := &s3.ListObjectsV2Input{
Bucket: aws.String(bucket),
}
for {
resp, err := svc.ListObjectsV2(listObjectsInput)
if err != nil {
return err
}
if len(resp.Contents) == 0 {
fmt.Println("No objects found in the bucket.")
break
}
var objectsToDelete []*s3.ObjectIdentifier
for _, item := range resp.Contents {
objectsToDelete = append(objectsToDelete, &s3.ObjectIdentifier{
Key: item.Key,
})
}
deleteObjectsInput := &s3.DeleteObjectsInput{
Bucket: aws.String(bucket),
Delete: &s3.Delete{
Objects: objectsToDelete,
Quiet: aws.Bool(true),
},
}
_, err = svc.DeleteObjects(deleteObjectsInput)
if err != nil {
return err
}
fmt.Printf("Deleted %d objects from bucket %s\n", len(objectsToDelete), bucket)
if !aws.BoolValue(resp.IsTruncated) {
break
}
listObjectsInput.ContinuationToken = resp.NextContinuationToken
}
fmt.Println("All objects deleted successfully.")
return nil
}

View File

@ -3,6 +3,8 @@ package services
import (
"net/http"
"netina/commands"
"netina/database"
"netina/models"
cm "netina/models/commands"
"netina/queries"
plan_repository "netina/repositories/plan"
@ -18,16 +20,29 @@ type PlanService struct {
}
func (s *PlanService) CreatePlan(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
plan := new(cm.CreatePlanCommand)
if err := c.Bind(plan); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
}
if err := validation.ValidateStruct(plan); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
handler := commands.CreatePlanHandler{Repository: s.CommandRepo}
if err := handler.Handle(*plan); err != nil {
if err := handler.Handle(*plan , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -50,6 +65,16 @@ func (s *PlanService) GetPlan(c echo.Context) error {
}
func (s *PlanService) UpdatePlan(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid plan ID"})
@ -64,7 +89,7 @@ func (s *PlanService) UpdatePlan(c echo.Context) error {
}
handler := commands.UpdatePlanHandler{Repository: s.CommandRepo}
updatedPlan, err := handler.Handle(uint(id), *plan)
updatedPlan, err := handler.Handle(uint(id), *plan , u.Name)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -85,3 +110,17 @@ func (s *PlanService) RemovePlan(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
func FindPlan(id uint) (*models.Plan , error) {
db := database.Db()
var Plan models.Plan
if err := db.Where("is_removed = ?" , false).Where("plan_id = ?" , id).First(&Plan).Error; err != nil {
return nil , err
}
return &Plan , nil
}

View File

@ -3,6 +3,7 @@ package services
import (
"net/http"
"netina/commands"
"netina/models"
cm "netina/models/commands"
"netina/queries"
Role_repository "netina/repositories/role"
@ -18,6 +19,16 @@ type RoleService struct {
}
func (s *RoleService) CreateRole(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
role := new(cm.CreateRoleCommand)
if err := c.Bind(role); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
@ -27,7 +38,7 @@ func (s *RoleService) CreateRole(c echo.Context) error {
}
handler := commands.CreateRoleHandler{Repository: s.CommandRepo}
if err := handler.Handle(*role); err != nil {
if err := handler.Handle(*role , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -50,6 +61,16 @@ func (s *RoleService) GetRole(c echo.Context) error {
}
func (s *RoleService) UpdateRole(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid role ID"})
@ -64,7 +85,7 @@ func (s *RoleService) UpdateRole(c echo.Context) error {
}
handler := commands.UpdateRoleHandler{Repository: s.CommandRepo}
updatedRole, err := handler.Handle(uint(id), *role)
updatedRole, err := handler.Handle(uint(id), *role , u.Name)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}

View File

@ -8,7 +8,7 @@ import (
func Sms(phoneNumber string , loginCode string) {
api := kavenegar.New("65334B6A70303233432B7A6530795A51683134524945742F74397161785568512B794966623245744C2F773D")
receptor := phoneNumber
template := "verify"
template := "login-netina"
token := loginCode
params := &kavenegar.VerifyLookupParam{
}

View File

@ -3,6 +3,7 @@ package services
import (
"net/http"
"netina/commands"
"netina/models"
cm "netina/models/commands"
"netina/queries"
store_repository "netina/repositories/store"
@ -18,6 +19,16 @@ type StoreService struct {
}
func (s *StoreService) CreateStore(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
store := new(cm.CreateStoreCommand)
if err := c.Bind(store); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
@ -26,8 +37,13 @@ func (s *StoreService) CreateStore(c echo.Context) error {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
_ , err = FindOwner(store.Owner_id)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid owner ID"})
}
handler := commands.CreateStoreHandler{Repository: s.CommandRepo}
if err := handler.Handle(*store); err != nil {
if err := handler.Handle(*store , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -64,6 +80,16 @@ func (s *StoreService) GetStoresList(c echo.Context) error {
}
func (s *StoreService) UpdateStore(c echo.Context) error {
user := c.Get("user").(*models.JWTClaims)
if user == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(user.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid store ID"})
@ -77,8 +103,13 @@ func (s *StoreService) UpdateStore(c echo.Context) error {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
_ , err = FindOwner(store.Owner_id)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid owner ID"})
}
handler := commands.UpdateStoreHandler{Repository: s.CommandRepo}
updatedStore, err := handler.Handle(uint(id), *store)
updatedStore, err := handler.Handle(uint(id), *store , u.Name)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}

56
services/upload.go 100644
View File

@ -0,0 +1,56 @@
package services
import (
"io"
"net/http"
"os"
"github.com/labstack/echo/v4"
)
func Upload(c echo.Context) error {
file, err := c.FormFile("file")
if err != nil {
return err
}
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
// Read the file header to determine the MIME type
buff := make([]byte, 512)
if _, err := src.Read(buff); err != nil {
return err
}
filetype := http.DetectContentType(buff)
// Verify if the file is a ZIP file
if filetype != "application/zip" && filetype != "application/x-zip-compressed" {
return c.JSON(http.StatusBadRequest, map[string]string{
"error": "The uploaded file is not a ZIP file",
})
}
// Reset the file pointer to the beginning
if _, err := src.Seek(0, io.SeekStart); err != nil {
return err
}
// Destination
dst, err := os.Create("./uploads/" + file.Filename)
if err != nil {
return err
}
if _, err = io.Copy(dst, src); err != nil {
return err
}
return c.JSON(http.StatusOK, map[string]string{
"message": "File uploaded successfully",
})
}

View File

@ -3,6 +3,7 @@ package services
import (
"net/http"
"netina/commands"
"netina/database"
"netina/models"
cm "netina/models/commands"
"netina/queries"
@ -19,6 +20,16 @@ type UserService struct {
}
func (s *UserService) CreateUser(c echo.Context) error {
usr := c.Get("user").(*models.JWTClaims)
if usr == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(usr.ID)
if err != nil {
return err
}
user := new(cm.CreateUserCommand)
if err := c.Bind(user); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request payload"})
@ -28,7 +39,7 @@ func (s *UserService) CreateUser(c echo.Context) error {
}
handler := commands.CreateUserHandler{Repository: s.CommandRepo}
if err := handler.Handle(*user); err != nil {
if err := handler.Handle(*user , u.Name); err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -69,6 +80,16 @@ func (s *UserService) GetUserByPhoneNumber(c echo.Context) error {
func (s *UserService) UpdateUser(c echo.Context) error {
usr := c.Get("user").(*models.JWTClaims)
if usr == nil {
return echo.ErrUnauthorized
}
u , err := FindUser(usr.ID)
if err != nil {
return err
}
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid User ID"})
@ -83,7 +104,7 @@ func (s *UserService) UpdateUser(c echo.Context) error {
}
handler := commands.UpdateUserHandler{Repository: s.CommandRepo}
updatedUser, err := handler.Handle(uint(id), *User)
updatedUser, err := handler.Handle(uint(id), *User , u.Name)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
@ -104,3 +125,16 @@ func (s *UserService) RemoveUser(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
func FindUser(id uint)(*models.User , error) {
db := database.Db()
var user models.User
if err := db.Where("is_removed = ?" , false).Where("user_id = ?" , id).First(&user).Error; err != nil {
return nil , err
}
return &user , nil
}