new file: api/Dockerfile
new file: api/bin/api.exe new file: api/cmd/main.go new file: api/go.mod new file: api/go.sum new file: api/src/configs/APIserver.go new file: api/src/configs/DBconfig.go new file: api/src/initializers/PGQL_DB.go new file: api/src/initializers/Routing.go new file: api/src/models/Contacts.go new file: api/src/models/Essence.go new file: api/src/models/Point.go new file: api/src/models/authDataStructs.go new file: api/src/models/user.go new file: api/src/rt/admin/users.go new file: api/src/rt/auth/Login.go new file: api/src/rt/auth/Registr.go new file: api/src/rt/auth/authAdminMiddlware.go new file: api/src/rt/auth/authMiddleware.go new file: api/src/rt/auth/auth_test.go new file: api/src/rt/prf/AuthUserMiddleWare.go new file: api/src/rt/prf/profile.go new file: api/src/rt/srch/search.go new file: api/src/storages/psql/psql.go new file: docker-compose.yml Changes not staged for commit: modified: ../.env deleted: ../api/Dockerfile deleted: ../api/Makefile deleted: ../api/bin/api.exe deleted: ../api/cmd/main.go deleted: ../api/go.mod deleted: ../api/go.sum deleted: ../api/src/configs/APIserver.go deleted: ../api/src/configs/DBconfig.go deleted: ../api/src/initializers/PGQL_DB.go deleted: ../api/src/initializers/Routing.go deleted: ../api/src/models/Contacts.go deleted: ../api/src/models/Essence.go deleted: ../api/src/models/Point.go deleted: ../api/src/models/authDataStructs.go deleted: ../api/src/models/user.go deleted: ../api/src/rt/admin/users.go deleted: ../api/src/rt/auth/Login.go deleted: ../api/src/rt/auth/Registr.go deleted: ../api/src/rt/auth/authAdminMiddlware.go deleted: ../api/src/rt/auth/authMiddleware.go deleted: ../api/src/rt/auth/auth_test.go deleted: ../api/src/rt/prf/AuthUserMiddleWare.go deleted: ../api/src/rt/prf/profile.go deleted: ../api/src/rt/srch/search.go deleted: ../api/src/storages/psql/psql.go deleted: ../db/docker-compose.yml modified: ../docker-compose.yaml movve file tino new directo for towo service rest api and d
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
FROM golang:1.22.5
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go mod tidy
|
||||||
|
|
||||||
|
RUN go build -o bin/api cmd/main.go
|
||||||
|
|
||||||
|
ENTRYPOINT [ "bin/api" ]
|
||||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/configs"
|
||||||
|
"api/src/initializers"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO write the tests
|
||||||
|
|
||||||
|
var APIServerCnf configs.APIserver
|
||||||
|
var PSQLCnf configs.PSQLConfig
|
||||||
|
var SecretKey = []byte(os.Getenv("SECRET_KEY"))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
slog.Info("Start")
|
||||||
|
initializers.InitChiRouting()
|
||||||
|
initializers.InitDBconnection()
|
||||||
|
slog.Info("server is closed", "info", <-initializers.Done)
|
||||||
|
slog.Info("End")
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
module api
|
||||||
|
|
||||||
|
go 1.22.5
|
||||||
|
|
||||||
|
require github.com/go-chi/chi/v5 v5.1.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
|
golang.org/x/crypto v0.25.0
|
||||||
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
|
golang.org/x/text v0.16.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
gorm.io/driver/postgres v1.5.9
|
||||||
|
gorm.io/gorm v1.25.11
|
||||||
|
)
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
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/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||||
|
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
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-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||||
|
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
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.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||||
|
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||||
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
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/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
|
||||||
|
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||||
|
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||||
|
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package configs
|
||||||
|
|
||||||
|
import(
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
type APIserver struct {
|
||||||
|
Server_port string
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package configs
|
||||||
|
|
||||||
|
type PSQLConfig struct {
|
||||||
|
Db_user string
|
||||||
|
Db_password string
|
||||||
|
Db_name string
|
||||||
|
Db_port string
|
||||||
|
Host_db string
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package initializers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/storages/psql"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitDBconnection() {
|
||||||
|
slog.Info("Init DB connection")
|
||||||
|
dsn := fmt.Sprintf(
|
||||||
|
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Yekaterinburg",
|
||||||
|
os.Getenv("PGHOST"),
|
||||||
|
os.Getenv("PGUSER"),
|
||||||
|
os.Getenv("PGPASSWORD"),
|
||||||
|
os.Getenv("PGDATABASE"),
|
||||||
|
os.Getenv("PGPORT"),
|
||||||
|
)
|
||||||
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||||
|
Logger: logger.Default.LogMode(logger.Info),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to connect database", "error", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
psql.PSQL_GORM_DB = db
|
||||||
|
sql, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to get database", "error", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
err = sql.Ping()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("failed to ping database", "error", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
slog.Info("connected to database")
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package initializers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/rt/admin"
|
||||||
|
"api/src/rt/auth"
|
||||||
|
"api/src/rt/prf"
|
||||||
|
"api/src/rt/srch"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Done = make(chan bool)
|
||||||
|
|
||||||
|
func InitChiRouting() {
|
||||||
|
slog.Info("Init routing")
|
||||||
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
// middlewares
|
||||||
|
r.Use(middleware.Logger)
|
||||||
|
r.Use(middleware.Timeout(60 * time.Second))
|
||||||
|
r.Use(middleware.RequestID)
|
||||||
|
r.Use(middleware.CleanPath)
|
||||||
|
r.Use(middleware.Heartbeat("/ping"))
|
||||||
|
r.Use(middleware.NoCache)
|
||||||
|
r.Use(middleware.Recoverer)
|
||||||
|
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
w.Write([]byte("route does not exist"))
|
||||||
|
})
|
||||||
|
r.MethodNotAllowed(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(405)
|
||||||
|
w.Write([]byte("method is not valid"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// public Routes
|
||||||
|
r.Group(func(r chi.Router) {
|
||||||
|
r.Post("/signup", auth.Register) // register
|
||||||
|
r.Post("/signin", auth.Login) // signin
|
||||||
|
r.Get("/search", srch.Search)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Private Routes
|
||||||
|
// Require Authentication
|
||||||
|
r.Group(func(r chi.Router) {
|
||||||
|
r.Use(auth.AuthMiddleware)
|
||||||
|
r.Get("/profile", prf.Profile)
|
||||||
|
r.Get("/allUsersAdm", admin.GetAllUser)
|
||||||
|
r.Route("/admin", func(r chi.Router) {
|
||||||
|
r.Use(auth.AuthAdminMiddleware)
|
||||||
|
r.Get("/allUsersAdm", admin.GetAllUser) // all users get
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// up server on os.Getenv("SERVER_PORT") port on gorutin
|
||||||
|
go func() {
|
||||||
|
defer close(Done)
|
||||||
|
err := http.ListenAndServe(":"+os.Getenv("SERVER_PORT"), r)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Can't start server: ", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
type Contact struct {
|
||||||
|
Id uuid.UUID `json:"id" gorm:"type:uuid;primaryKey;unique;AutoIncrement:false"`
|
||||||
|
Email string `json:"email" gorm:"type:string"`
|
||||||
|
Phone string `json:"phone" gorm:"type:string"`
|
||||||
|
Address string `json:"address" gorm:"type:string"`
|
||||||
|
Point Point `json:"point" gorm:"type:struct"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
type Essence struct {
|
||||||
|
Id uuid.UUID `json:"id" gorm:"type:uuid;primaryKey;unique;AutoIncrement:false"`
|
||||||
|
Name string `json:"name" gorm:"type:string"`
|
||||||
|
Type string `json:"type" gorm:"type:string"`
|
||||||
|
Contact Contact `json:"contact" gorm:"type:struct"`
|
||||||
|
ShortDescription string `json:"shortDesc" gorm:"type:string"`
|
||||||
|
Description string `json:"description" gorm:"type:string"`
|
||||||
|
AverageBill int `json:"number" gorm:"type:int"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
Id uuid.UUID `json:"id" gorm:"type:uuid;primaryKey;unique;AutoIncrement:false"`
|
||||||
|
Latitude int64 `json:"latitude" gorm:"type:int64"`
|
||||||
|
Longitude int64 `json:"longitude" gorm:"type:int64"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Credentials struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Role string `json:"role"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Claims struct {
|
||||||
|
jwt.RegisteredClaims
|
||||||
|
Email string `json:"email"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Role string `json:"role"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/google/uuid"
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Id uuid.UUID `json:"id" gorm:"type:uuid;primaryKey;unique;AutoIncrement:false"`
|
||||||
|
Name string `json:"name" gorm:"type:string"`
|
||||||
|
Email string `json:"email" gorm:"type:string;index"`
|
||||||
|
Password string `json:"password" gorm:"type:string;index"`
|
||||||
|
Phone string `json:"phone" gorm:"type:string;index"`
|
||||||
|
Role string `json:"role" gorm:"type:string;index"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/models"
|
||||||
|
"api/src/storages/psql"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAllUser(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var users []models.User
|
||||||
|
|
||||||
|
qr := psql.PSQL_GORM_DB.Find(&users)
|
||||||
|
if qr.Error != nil {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsData, err := json.Marshal(users)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusNotAcceptable)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(jsData))
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/models"
|
||||||
|
"api/src/storages/psql"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var jwtKey = []byte(os.Getenv("SECRET_KEY"))
|
||||||
|
|
||||||
|
func Login(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var creds models.Credentials
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check user
|
||||||
|
var user models.User
|
||||||
|
// get user by email
|
||||||
|
result := psql.PSQL_GORM_DB.Where("email = ?", creds.Email).First(&user)
|
||||||
|
if result.Error != nil || !checkPasswordHash(creds.Password, user.Password) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create jwt token
|
||||||
|
expirationtime := time.Now().Add(5 * time.Minute)
|
||||||
|
claims := &models.Claims{
|
||||||
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
|
ExpiresAt: jwt.NewNumericDate(expirationtime),
|
||||||
|
},
|
||||||
|
Email: user.Email,
|
||||||
|
Phone: user.Phone,
|
||||||
|
Role: user.Role,
|
||||||
|
}
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
tokenString, err := token.SignedString(jwtKey)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "token",
|
||||||
|
Value: tokenString,
|
||||||
|
Expires: expirationtime,
|
||||||
|
})
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPasswordHash(password, hash string) bool {
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/models"
|
||||||
|
"api/src/storages/psql"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Register(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var Credentials models.Credentials
|
||||||
|
// Decoe body
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&Credentials); err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// shep password
|
||||||
|
hashedPassword, err := hashPassword(Credentials.Password)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id := uuid.New()
|
||||||
|
|
||||||
|
user := models.User{
|
||||||
|
Id: id,
|
||||||
|
Name: Credentials.Name,
|
||||||
|
Email: Credentials.Email,
|
||||||
|
Password: hashedPassword,
|
||||||
|
Phone: Credentials.Phone,
|
||||||
|
Role: Credentials.Role,
|
||||||
|
}
|
||||||
|
result := psql.PSQL_GORM_DB.Create(&user)
|
||||||
|
if result.Error != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hashPassword(password string) (string, error) {
|
||||||
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||||
|
return string(bytes), err
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/models"
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthAdminMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
c, err := r.Cookie("token")
|
||||||
|
if err != nil {
|
||||||
|
if err == http.ErrNoCookie {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tknStr := c.Value
|
||||||
|
claims := &models.Claims{}
|
||||||
|
|
||||||
|
tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return jwtKey, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == jwt.ErrSignatureInvalid {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !tkn.Valid {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims.Role != "admin" {
|
||||||
|
w.WriteHeader(http.StatusNonAuthoritativeInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(r.Context(), "email", claims.Email)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"api/src/models"
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
c, err := r.Cookie("token")
|
||||||
|
if err != nil {
|
||||||
|
if err == http.ErrNoCookie {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tknStr := c.Value
|
||||||
|
claims := &models.Claims{}
|
||||||
|
|
||||||
|
tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return jwtKey, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == jwt.ErrSignatureInvalid {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !tkn.Valid {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(r.Context(), "email", claims.Email)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_hashPass(t *testing.T) {
|
||||||
|
password := "some hard password"
|
||||||
|
hash, _ := hashPassword(password)
|
||||||
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Falis by: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package prf
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func AuthUserMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package prf
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func Profile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package srch
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func Search(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package psql
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
var PSQL_GORM_DB *gorm.DB
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: db
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "${PGPORT}:${PGPORT}"
|
||||||
|
volumes:
|
||||||
|
- postgres-db:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${PGUSER}
|
||||||
|
- POSTGRES_PASSWORD=${PGPASSWORD}
|
||||||
|
- POSTGRES_DB=${PGDATABASE}
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
api:
|
||||||
|
container_name: api
|
||||||
|
build:
|
||||||
|
context: ./api
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "${SERVER_PORT}:${SERVER_PORT}"
|
||||||
|
volumes:
|
||||||
|
- api:/usr/src/app
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
command: ./bin/api
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-db:
|
||||||
|
api:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user