40
loading...
This website collects cookies to deliver better user experience
postgres
user with password postgres
.postgres
user:sudo service postgresql start
sudo -u postgres psql
CREATE DATABASE rgb;
go get github.com/go-pg/pg/v10
. This will install version 10 of go-pg
module, which is latest version at the time of writing this guide. Now create new directory internal/database/
and file database.go
inside of it.package database
import (
"github.com/go-pg/pg/v10"
)
func NewDBOptions() *pg.Options {
return &pg.Options{
Addr: "localhost:5432",
Database: "rgb",
User: "postgres",
Password: "postgres",
}
}
internal/store/store.go
where we will setup database connection to be used by our store
package which will be the only one communicating with database.package store
import (
"log"
"github.com/go-pg/pg/v10"
)
// Database connector
var db *pg.DB
func SetDBConnection(dbOpts *pg.Options) {
if dbOpts == nil {
log.Panicln("DB options can't be nil")
} else {
db = pg.Connect(dbOpts)
}
}
func GetDBConnection() *pg.DB { return db }
db
which will serve as a database connector for store package. We also have two functions, one to set that database connector, and one to get it. Function SetDBConnection()
will be used immediately because we need to set our database connector. As already said, only store package will connect to database and db
variable is available in whole package. So, what do we need GetDBConnection()
for? Well, we actually don't need it yet, but we will need it in next section to run migrations, because that will be happening in separate small app, as you will see soon. For now, let's only set database connector inside of internal/server/server.go
file by adding line store.SetDBConnection(database.NewDBOptions())
:package server
import (
"rgb/internal/database"
"rgb/internal/store"
)
func Start() {
store.SetDBConnection(database.NewDBOptions())
router := setRouter()
// Start listening and serving requests
router.Run(":8080")
}
internal/store/users.go
file:package store
import "errors"
type User struct {
ID int
Username string `binding:"required,min=5,max=30"`
Password string `binding:"required,min=7,max=32"`
}
func AddUser(user *User) error {
_, err := db.Model(user).Returning("*").Insert()
if err != nil {
return err
}
return nil
}
func Authenticate(username, password string) (*User, error) {
user := new(User)
if err := db.Model(user).Where(
"username = ?", username).Select(); err != nil {
return nil, err
}
if password != user.Password {
return nil, errors.New("Password not valid.")
}
return user, nil
}
internal/server/user.go
:package server
import (
"net/http"
"rgb/internal/store"
"github.com/gin-gonic/gin"
)
func signUp(ctx *gin.Context) {
user := new(store.User)
if err := ctx.Bind(user); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := store.AddUser(user); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{
"msg": "Signed up successfully.",
"jwt": "123456789",
})
}
func signIn(ctx *gin.Context) {
user := new(store.User)
if err := ctx.Bind(user); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := store.Authenticate(user.Username, user.Password)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Sign in failed."})
return
}
ctx.JSON(http.StatusOK, gin.H{
"msg": "Signed in successfully.",
"jwt": "123456789",
})
}