Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send to staging #64

Merged
merged 34 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2323197
Merge pull request #38 from hngprojects/main
vicradon Jul 19, 2024
cc80986
database initialize
Cyberguru1 Jul 19, 2024
8f8d5e6
setup database tables, database seeding, and automigration
Micah-Shallom Jul 19, 2024
c6c0325
database initialize
Cyberguru1 Jul 19, 2024
b8d4755
setup user controller
Micah-Shallom Jul 19, 2024
26f528c
database initialize
Cyberguru1 Jul 19, 2024
444e67e
Merge github.com:Micah-Shallom/hng_boilerplate_golang_web
Cyberguru1 Jul 19, 2024
d8e3675
fix seed data read
Cyberguru1 Jul 19, 2024
41dfb79
changes
Micah-Shallom Jul 19, 2024
ca01daa
completed db setup
Micah-Shallom Jul 19, 2024
8f2a98a
change uuid v7
Micah-Shallom Jul 19, 2024
f346af1
changed uuid to version 7 format
Micah-Shallom Jul 19, 2024
9ba6ac3
"Updated environment variables and PostgreSQL service configuration i…
ekedonald Jul 20, 2024
f9075e6
database setup fix
Cyberguru1 Jul 20, 2024
ec84712
Merge pull request #48 from hngprojects/main
vicradon Jul 20, 2024
fb844da
Merge branch 'hngprojects:main' into main
ekedonald Jul 20, 2024
ac770c5
"Created and added 'install_rabbitmq.sh' to the list of scripts in in…
ekedonald Jul 20, 2024
f06ac0f
implemented receivers for data query
Micah-Shallom Jul 20, 2024
4130c9b
api for organization creation
Cyberguru1 Jul 20, 2024
aa7ef5f
Merge pull request #43 from Micah-Shallom/main
NwokoyeChigozie Jul 20, 2024
8942bd4
Merge pull request #51 from ekedonald/main
vicradon Jul 20, 2024
9d94a56
implemented, auth, userSignup, userLogin, orgcreation and respective …
Cyberguru1 Jul 20, 2024
78c59dc
Merge pull request #57 from Cyberguru1/main
NwokoyeChigozie Jul 21, 2024
368a7b9
fix log file path
Cyberguru1 Jul 21, 2024
aafb271
Merge pull request #60 from Cyberguru1/main
Cyberguru1 Jul 21, 2024
e3e43d2
Merge pull request #1 from hngprojects/main
Cyberguru1 Jul 21, 2024
0b69927
fix env read
Cyberguru1 Jul 21, 2024
713a20a
Merge branch 'main' of github.com:Cyberguru1/hng_boilerplate_golang_web
Cyberguru1 Jul 21, 2024
5f50f79
check port env
Cyberguru1 Jul 21, 2024
93fe568
fix viper env bind err
Cyberguru1 Jul 21, 2024
36407bb
fix viper env bind err
Cyberguru1 Jul 21, 2024
e52ee7c
fix viper env bind err
Cyberguru1 Jul 21, 2024
9c31693
Merge branch 'dev' into main
Cyberguru1 Jul 21, 2024
c42f8ea
Merge pull request #61 from Cyberguru1/main
Cyberguru1 Jul 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/hngprojects/hng_boilerplate_golang_web

go 1.19

toolchain go1.22.2

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/didip/tollbooth v4.0.2+incompatible
Expand All @@ -12,10 +14,13 @@ require (
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.22.0
github.com/gofrs/uuid v4.4.0+incompatible
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/jeanphorn/log4go v0.0.0-20231225120528-d93eb9001e51
github.com/mitchellh/mapstructure v1.5.0
github.com/nyaruka/phonenumbers v1.3.6
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
golang.org/x/crypto v0.23.0
gorm.io/driver/postgres v1.5.9
gorm.io/gorm v1.25.10
)
Expand All @@ -41,7 +46,6 @@ require (
github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
Expand All @@ -59,7 +63,6 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.6.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
Expand Down
37 changes: 33 additions & 4 deletions internal/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package config
import (
"log"

"github.com/hngprojects/hng_boilerplate_golang_web/utility"

"github.com/mitchellh/mapstructure"

"github.com/spf13/viper"

"github.com/hngprojects/hng_boilerplate_golang_web/utility"
)

// Setup initialize configuration
Expand All @@ -22,10 +26,20 @@ func Setup(logger *utility.Logger, name string) *Configuration {
viper.AddConfigPath(".")

if err := viper.ReadInConfig(); err != nil {
log.Fatalf("Error reading config file, %s", err)
}
// remove from fatal to Printf to check env
log.Printf("Error reading config file, %s", err)
log.Printf("Reading from environment variable")

viper.AutomaticEnv()

viper.AutomaticEnv()
var config BaseConfig

// bind config keys to viper
err := BindKeys(viper.GetViper(), config)
if err != nil {
log.Fatalf("Unable to bindkeys in struct, %v", err)
}
}

err := viper.Unmarshal(&baseConfiguration)
if err != nil {
Expand All @@ -44,3 +58,18 @@ func Setup(logger *utility.Logger, name string) *Configuration {
func GetConfig() *Configuration {
return Config
}

func BindKeys(v *viper.Viper, input interface{}) error {

envKeysMap := &map[string]interface{}{}
if err := mapstructure.Decode(input, &envKeysMap); err != nil {
return err
}
for k := range *envKeysMap {
if bindErr := viper.BindEnv(k); bindErr != nil {
return bindErr
}
}

return nil
}
1 change: 1 addition & 0 deletions internal/config/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (config *BaseConfig) SetupConfigurationn() *Configuration {
exemptFromThrottle := []string{}
json.Unmarshal([]byte(config.TRUSTED_PROXIES), &trustedProxies)
json.Unmarshal([]byte(config.EXEMPT_FROM_THROTTLE), &exemptFromThrottle)

if config.SERVER_PORT == "" {
config.SERVER_PORT = os.Getenv("PORT")
}
Expand Down
16 changes: 16 additions & 0 deletions internal/models/migrations/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package migrations

import "github.com/hngprojects/hng_boilerplate_golang_web/internal/models"

func AuthMigrationModels() []interface{} {
return []interface{}{
models.Organisation{},
models.Profile{},
models.Product{},
models.User{},
} // an array of db models, example: User{}
}

func AlterColumnModels() []AlterColumn {
return []AlterColumn{}
}
10 changes: 0 additions & 10 deletions internal/models/migrations/transactions_migrations.go

This file was deleted.

47 changes: 47 additions & 0 deletions internal/models/organisation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package models

import (
"time"

"gorm.io/gorm"

"github.com/hngprojects/hng_boilerplate_golang_web/pkg/repository/storage/postgresql"
)

type Organisation struct {
ID string `gorm:"type:uuid;primaryKey;unique;not null" json:"id"`
Name string `gorm:"type:varchar(255);not null" json:"name"`
Description string `gorm:"type:text" json:"description"`
Email string `gorm:"type:varchar(255);unique" json:"email"`
State string `gorm:"type:varchar(255)" json:"state"`
Industry string `gorm:"type:varchar(255)" json:"industry"`
Type string `gorm:"type:varchar(255)" json:"type"`
Address string `gorm:"type:varchar(255)" json:"address"`
Country string `gorm:"type:varchar(255)" json:"country"`
OwnerID string `gorm:"type:uuid;" json:"owner_id"`
Users []User `gorm:"many2many:user_organisations;foreignKey:ID;joinForeignKey:org_id;References:ID;joinReferences:user_id"`
CreatedAt time.Time `gorm:"column:created_at; not null; autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at; null; autoUpdateTime" json:"updated_at"`
}

type CreateOrgRequestModel struct {
Name string `json:"name" validate:"required,min=2,max=255"`
Description string `json:"description" `
Email string `json:"email" validate:"required"`
State string `json:"state" validate:"required"`
Industry string `json:"industry" validate:"required"`
Type string `json:"type" validate:"required"`
Address string `json:"address" validate:"required"`
Country string `json:"country" validate:"required"`
}

func (c *Organisation) CreateOrganisation(db *gorm.DB) error {

err := postgresql.CreateOneRecord(db, &c)

if err != nil {
return err
}

return nil
}
12 changes: 12 additions & 0 deletions internal/models/product.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package models

import "time"

type Product struct {
ID string `gorm:"type:uuid;primaryKey" json:"product_id"`
Name string `gorm:"column:name; type:varchar(255); not null" json:"name"`
Description string `gorm:"column:description;type:text;" json:"description"`
OwnerID string `gorm:"type:uuid;" json:"owner_id"`
CreatedAt time.Time `gorm:"column:created_at; not null; autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at; null; autoUpdateTime" json:"updated_at"`
}
14 changes: 14 additions & 0 deletions internal/models/profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package models

import "time"

type Profile struct {
ID string `gorm:"type:uuid;primary_key" json:"profile_id"`
FirstName string `gorm:"column:first_name; type:text; not null" json:"first_name"`
LastName string `gorm:"column:last_name; type:text;not null" json:"last_name"`
Phone string `gorm:"type:varchar(255)" json:"phone"`
AvatarURL string `gorm:"type:varchar(255)" json:"avatar_url"`
Userid string `gorm:"type:uuid;" json:"user_id"`
CreatedAt time.Time `gorm:"column:created_at; not null; autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at; null; autoUpdateTime" json:"updated_at"`
}
82 changes: 82 additions & 0 deletions internal/models/seed/seed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package seed

import (
"fmt"

"gorm.io/gorm"

"github.com/hngprojects/hng_boilerplate_golang_web/internal/models"
"github.com/hngprojects/hng_boilerplate_golang_web/pkg/repository/storage/postgresql"
"github.com/hngprojects/hng_boilerplate_golang_web/utility"
)

func SeedDatabase(db *gorm.DB) {
// instantiate uuid

Userid1 := utility.GenerateUUID()
user1 := models.User{
ID: Userid1,
Name: "John Doe",
Email: "[email protected]",
Password: utility.RandomString(20),
Profile: models.Profile{
ID: utility.GenerateUUID(),
FirstName: "John",
LastName: "Doe",
Phone: "1234567890",
AvatarURL: "http://example.com/avatar.jpg",
},
Products: []models.Product{
{ID: utility.GenerateUUID(), Name: "Product1", Description: "Description1", OwnerID: Userid1},
{ID: utility.GenerateUUID(), Name: "Product2", Description: "Description2", OwnerID: Userid1},
},
}

Userid2 := utility.GenerateUUID()
user2 := models.User{
ID: Userid2,
Name: "Jane Doe",
Password: utility.RandomString(20),
Email: "[email protected]",
Profile: models.Profile{
ID: utility.GenerateUUID(),
FirstName: "Jane",
LastName: "Doe",
Phone: "0987654321",
AvatarURL: "http://example.com/avatar2.jpg",
},
Products: []models.Product{
{ID: utility.GenerateUUID(), Name: "Product3", Description: "Description3", OwnerID: Userid2},
{ID: utility.GenerateUUID(), Name: "Product4", Description: "Description4", OwnerID: Userid2},
},
}

organisations := []models.Organisation{
{ID: utility.GenerateUUID(), Name: "Org1", Email: fmt.Sprintf(utility.RandomString(4)+"@email.com"),Description: "Description1", OwnerID: Userid1},
{ID: utility.GenerateUUID(), Name: "Org2", Email: fmt.Sprintf(utility.RandomString(4)+"@email.com"),Description: "Description2", OwnerID: Userid1},
{ID: utility.GenerateUUID(), Name: "Org3", Email: fmt.Sprintf(utility.RandomString(4)+"@email.com"),Description: "Description3", OwnerID: Userid2},
}

var existingUser models.User
if err := db.Preload("Profile").Preload("Products").Where("email = ?", user1.Email).First(&existingUser).Error; err != nil {
if err == gorm.ErrRecordNotFound {
postgresql.CreateOneRecord(db, &user1)
postgresql.CreateOneRecord(db, &user2)
for _, org := range organisations {
postgresql.CreateOneRecord(db, &org)
}
fmt.Println("Users and organisations seeded.")

// Add users to organisations
existingUser.AddUserToOrganisation(db, &user1, []interface{}{&organisations[0], &organisations[1]})
existingUser.AddUserToOrganisation(db, &user2, []interface{}{&organisations[0], &organisations[1], &organisations[2]})
fmt.Println("Users added to organisations.")

} else {
fmt.Println("An error occurred: ", err)
}
} else {
fmt.Println("Users already exist, skipping seeding.")
}

}
67 changes: 67 additions & 0 deletions internal/models/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package models

import (
"time"

"gorm.io/gorm"

"github.com/hngprojects/hng_boilerplate_golang_web/pkg/repository/storage/postgresql"
)

type User struct {
ID string `gorm:"type:uuid;primaryKey;unique;not null" json:"id"`
Name string `gorm:"column:name; type:varchar(255)" json:"name"`
Email string `gorm:"column:email; type:varchar(255)" json:"email"`
Password string `gorm:"column:password; type:text; not null" json:"-"`
Profile Profile `gorm:"foreignKey:Userid;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"profile"`
Organisations []Organisation `gorm:"many2many:user_organisations;;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" json:"organisations" ` // many to many relationship
Products []Product `gorm:"foreignKey:OwnerID" json:"products"`
CreatedAt time.Time `gorm:"column:created_at; not null; autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at; null; autoUpdateTime" json:"updated_at"`
}

type CreateUserRequestModel struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
FirstName string `json:"first_name" validate:"required"`
LastName string `json:"last_name" validate:"required"`
UserName string `json:"username" validate:"required"`
PhoneNumber string `json:"phone_number"`
}

type LoginRequestModel struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}

func (u *User) AddUserToOrganisation(db *gorm.DB, user interface{}, orgs []interface{}) error {

// Add user to organisation
err := db.Model(user).Association("Organisations").Append(orgs...)
if err != nil {
return err
}

return nil
}

func (u *User) GetUserByID(db *gorm.DB, userID string) (User, error) {
var user User

if err := db.Preload("Profile").Preload("Products").Preload("Organisations").Where("id = ?", userID).First(&user).Error; err != nil {
return user, err
}

return user, nil
}

func (u *User) CreateUser(db *gorm.DB) error {

err := postgresql.CreateOneRecord(db, &u)

if err != nil {
return err
}

return nil
}
6 changes: 6 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"log"

"github.com/go-playground/validator/v10"

"github.com/hngprojects/hng_boilerplate_golang_web/internal/config"
"github.com/hngprojects/hng_boilerplate_golang_web/internal/models/migrations"
"github.com/hngprojects/hng_boilerplate_golang_web/internal/models/seed"
"github.com/hngprojects/hng_boilerplate_golang_web/pkg/repository/storage"
"github.com/hngprojects/hng_boilerplate_golang_web/pkg/repository/storage/postgresql"
"github.com/hngprojects/hng_boilerplate_golang_web/pkg/router"
Expand All @@ -19,12 +21,16 @@ func main() {
configuration := config.Setup(logger, "./app")

postgresql.ConnectToDatabase(logger, configuration.Database)

validatorRef := validator.New()

db := storage.Connection()

if configuration.Database.Migrate {
migrations.RunAllMigrations(db)

// call the seed function
seed.SeedDatabase(db.Postgresql)
}

r := router.Setup(logger, validatorRef, db, &configuration.App)
Expand Down
Loading
Loading