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

feat: add user repository #36

Merged
merged 7 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,3 @@ pgadmin-clean: pgadmin-rm
mocks:
mockery --name=UserRepository --srcpkg=./internal/domain/repository --output=./internal/domain/repository/mocks
mockery --name=UserService --srcpkg=./internal/domain/service --output=./internal/domain/service/mocks
mockery --name=PgConn --srcpkg=./internal/infrastructure/repository --output=./internal/infrastructure/repository/mocks
20 changes: 18 additions & 2 deletions cmd/http-rest-api/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
package main

import "fmt"
import (
"os"

"github.com/wizeline/CA-Microservices-Go/internal/infrastructure/config"
"github.com/wizeline/CA-Microservices-Go/internal/infrastructure/logger"
"github.com/wizeline/CA-Microservices-Go/pkg/app"
)

func main() {
fmt.Println("Hello HTTP REST API:", 123)
l := logger.NewZeroLog()
cfg := config.NewConfig()

api, clean, err := app.NewApiHTTP(cfg, l)
if err != nil {
l.Log().Err(err).Msg("http rest api startup failed")
os.Exit(1)
}
defer clean()

api.Start()
}
2 changes: 1 addition & 1 deletion deployments/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ EXPOSE ${PORT}
# USER MODE
USER ${USER}

ENTRYPOINT ["/usr/local/bin/http-api"]
ENTRYPOINT ["/usr/local/bin/camgo"]
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
Expand All @@ -22,7 +22,7 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
Expand All @@ -34,5 +34,6 @@ require (
github.com/spf13/viper v1.18.2
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.21.0
gopkg.in/yaml.v3 v3.0.1 // indirect
)
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v
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.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
Expand Down Expand Up @@ -69,13 +70,15 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
24 changes: 15 additions & 9 deletions internal/domain/entity/user.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package entity

import "time"
import (
"database/sql"
"time"
)

type User struct {
ID int
Name string
Username string
Password string
Email string
BirthDay time.Time
Active bool
ID int
FirstName string
LastName string
Email string
BirthDay time.Time

Username string
Passwd string
Active bool
LastLogin sql.NullTime

CreatedAt time.Time
UpdatedAt time.Time
UpdatedAt sql.NullTime
}
30 changes: 10 additions & 20 deletions internal/domain/repository/mocks/UserRepository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/domain/repository/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
var _ UserRepository = &mocks.UserRepository{}

type UserRepository interface {
Create(user entity.User) (int, error)
Create(user entity.User) error
Read(id int) (entity.User, error)
ReadAll() ([]entity.User, error)
Update(id int, data entity.User) error
Update(user entity.User) error
Delete(id int) error
}
17 changes: 9 additions & 8 deletions internal/infrastructure/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const defaultAppName = "camgo"
// Config is the representation of the application's configuration.
type Config struct {
Application Application
Server HTTPServer
HTTPServer HTTPServer
Database Database
}

Expand All @@ -28,8 +28,8 @@ func setDefaultConfig() {
viper.SetDefault("database.driver", "postgres")
viper.SetDefault("database.postgres.host", "localhost")
viper.SetDefault("database.postgres.port", 5432)
viper.SetDefault("database.postgres.user", "postgres")
viper.SetDefault("database.postgres.passwd", "")
viper.SetDefault("database.postgres.user", defaultAppName+"user")
viper.SetDefault("database.postgres.passwd", defaultAppName+"p4s5W0rD")
viper.SetDefault("database.postgres.dbname", defaultAppName)
}

Expand All @@ -45,18 +45,19 @@ func NewConfig() Config {
name: viper.GetString("application.name"),
version: viper.GetString("application.version"),
},
Server: HTTPServer{
HTTPServer: HTTPServer{
host: viper.GetString("http.server.host"),
port: viper.GetInt("http.server.port"),
shutdownTimeout: viper.GetDuration("http.server.shutdown.timeout"),
},
Database: Database{
driver: viper.GetString("database.driver"),
Postgres: PostgreSQL{
Host: viper.GetString("database.postgres.host"),
Port: viper.GetInt("database.postgres.port"),
User: viper.GetString("database.postgres.user"),
DBName: viper.GetString("database.postgres.dbname"),
host: viper.GetString("database.postgres.host"),
port: viper.GetInt("database.postgres.port"),
user: viper.GetString("database.postgres.user"),
passwd: viper.GetString("database.postgres.passwd"),
dbname: viper.GetString("database.postgres.dbname"),
},
},
}
Expand Down
12 changes: 6 additions & 6 deletions internal/infrastructure/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ func TestNewConfig(t *testing.T) {
name: defaultAppName,
version: "v0.0.0",
},
Server: HTTPServer{
HTTPServer: HTTPServer{
host: "localhost",
port: 8080,
shutdownTimeout: 15000000000,
},
Database: Database{
driver: "postgres",
Postgres: PostgreSQL{
Host: "localhost",
Port: 5432,
User: "postgres",
Passwd: "",
DBName: defaultAppName,
host: "localhost",
port: 5432,
user: defaultAppName + "user",
passwd: defaultAppName + "p4s5W0rD",
dbname: defaultAppName,
},
},
},
Expand Down
35 changes: 30 additions & 5 deletions internal/infrastructure/config/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,34 @@ func (db Database) Driver() string {

// PostgreSQL holds the configuration values of the postgresql database instances.
type PostgreSQL struct {
Host string
Port int
User string
Passwd string
DBName string
host string
port int
user string
passwd string
dbname string
}

// Host returns the host value set for the postgresql instance.
func (pg PostgreSQL) Host() string {
return pg.host
}

// Port returns the port value set for the postgresql instance.
func (pg PostgreSQL) Port() int {
return pg.port
}

// User returns the username value set for the postgresql instance.
func (pg PostgreSQL) User() string {
return pg.user
}

// Passwd returns the password value set for the postgresql instance.
func (pg PostgreSQL) Passwd() string {
return pg.passwd
}

// DBName returns the database name value set for the postgresql instance.
func (pg PostgreSQL) DBName() string {
return pg.dbname
}
1 change: 1 addition & 0 deletions internal/infrastructure/db/migration/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package migration
39 changes: 39 additions & 0 deletions internal/infrastructure/db/migration/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package migration

import (
"database/sql"
"fmt"
"os"
"path/filepath"

"github.com/wizeline/CA-Microservices-Go/internal/infrastructure/logger"
)

const migrationsDir = "internal/infrastructure/db/migration/v1"

type Migration struct {
name string
filename string
Up func(db *sql.DB, sqlContent string) error
Down func(db *sql.DB, sqlContent string) error
}

// Run applies the given migration functions
func Run(db *sql.DB, migrations []Migration, l logger.ZeroLog) error {
for _, m := range migrations {
l.Log().Debug().Str("name", m.name).Msg("applying migration")

path := filepath.Join(migrationsDir, m.filename)
sqlContent, err := os.ReadFile(path)
if err != nil {
// TODO: convert it to error migration type
return fmt.Errorf("failed reading SQL file %s: %s", m.filename, err)
}

if err := m.Up(db, string(sqlContent)); err != nil {
// TODO: convert it to error migration type
return fmt.Errorf("failed applying migration %s: %s", m.name, err)
}
}
return nil
}
20 changes: 20 additions & 0 deletions internal/infrastructure/db/migration/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package migration

import "database/sql"

// TODO: Implement migration functions for creating and dropping tables, modifying schema, or any other changes needed.
// Each migration function should be idempotent, meaning it can be run multiple times without causing issues.

var CreateUsersTable = Migration{
name: "CreateUsersTable",
filename: "001_create_users_table.sql",
Up: func(db *sql.DB, sqlContent string) error {
_, err := db.Exec(sqlContent)
return err
},
Down: func(db *sql.DB, sqlContent string) error {
// Implement the rollback logic if needed
_, err := db.Exec("DROP TABLE IF EXISTS users;")
return err
},
}
15 changes: 15 additions & 0 deletions internal/infrastructure/db/migration/v1/001_create_users_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
first_name VARCHAR (255) NOT NULL,
last_name VARCHAR (255) NOT NULL,
email VARCHAR (255) UNIQUE NOT NULL,
birthday DATE NOT NULL,

username VARCHAR (50) UNIQUE NOT NULL,
passwd TEXT NOT NULL,
active BOOLEAN DEFAULT FALSE,
last_login TIMESTAMP,

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
Empty file.
Loading