diff --git a/rest_api/api/Dockerfile b/rest_api/api/Dockerfile new file mode 100644 index 0000000..101f1b1 --- /dev/null +++ b/rest_api/api/Dockerfile @@ -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" ] \ No newline at end of file diff --git a/rest_api/api/bin/api.exe b/rest_api/api/bin/api.exe new file mode 100644 index 0000000..4dc983e Binary files /dev/null and b/rest_api/api/bin/api.exe differ diff --git a/rest_api/api/cmd/main.go b/rest_api/api/cmd/main.go new file mode 100644 index 0000000..464f07f --- /dev/null +++ b/rest_api/api/cmd/main.go @@ -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") +} \ No newline at end of file diff --git a/rest_api/api/go.mod b/rest_api/api/go.mod new file mode 100644 index 0000000..9e9c6fe --- /dev/null +++ b/rest_api/api/go.mod @@ -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 +) diff --git a/rest_api/api/go.sum b/rest_api/api/go.sum new file mode 100644 index 0000000..7526c32 --- /dev/null +++ b/rest_api/api/go.sum @@ -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= diff --git a/rest_api/api/src/configs/APIserver.go b/rest_api/api/src/configs/APIserver.go new file mode 100644 index 0000000..4769a67 --- /dev/null +++ b/rest_api/api/src/configs/APIserver.go @@ -0,0 +1,9 @@ +package configs + +import( + +) + +type APIserver struct { + Server_port string +} \ No newline at end of file diff --git a/rest_api/api/src/configs/DBconfig.go b/rest_api/api/src/configs/DBconfig.go new file mode 100644 index 0000000..018c986 --- /dev/null +++ b/rest_api/api/src/configs/DBconfig.go @@ -0,0 +1,9 @@ +package configs + +type PSQLConfig struct { + Db_user string + Db_password string + Db_name string + Db_port string + Host_db string +} \ No newline at end of file diff --git a/rest_api/api/src/initializers/PGQL_DB.go b/rest_api/api/src/initializers/PGQL_DB.go new file mode 100644 index 0000000..7f78620 --- /dev/null +++ b/rest_api/api/src/initializers/PGQL_DB.go @@ -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") +} \ No newline at end of file diff --git a/rest_api/api/src/initializers/Routing.go b/rest_api/api/src/initializers/Routing.go new file mode 100644 index 0000000..1bbfd7e --- /dev/null +++ b/rest_api/api/src/initializers/Routing.go @@ -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) + } + }() +} diff --git a/rest_api/api/src/models/Contacts.go b/rest_api/api/src/models/Contacts.go new file mode 100644 index 0000000..4b8708c --- /dev/null +++ b/rest_api/api/src/models/Contacts.go @@ -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"` +} diff --git a/rest_api/api/src/models/Essence.go b/rest_api/api/src/models/Essence.go new file mode 100644 index 0000000..7ea7382 --- /dev/null +++ b/rest_api/api/src/models/Essence.go @@ -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"` +} diff --git a/rest_api/api/src/models/Point.go b/rest_api/api/src/models/Point.go new file mode 100644 index 0000000..6af7794 --- /dev/null +++ b/rest_api/api/src/models/Point.go @@ -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"` +} diff --git a/rest_api/api/src/models/authDataStructs.go b/rest_api/api/src/models/authDataStructs.go new file mode 100644 index 0000000..2bdd814 --- /dev/null +++ b/rest_api/api/src/models/authDataStructs.go @@ -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"` +} diff --git a/rest_api/api/src/models/user.go b/rest_api/api/src/models/user.go new file mode 100644 index 0000000..93e3086 --- /dev/null +++ b/rest_api/api/src/models/user.go @@ -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"` +} diff --git a/rest_api/api/src/rt/admin/users.go b/rest_api/api/src/rt/admin/users.go new file mode 100644 index 0000000..174bd21 --- /dev/null +++ b/rest_api/api/src/rt/admin/users.go @@ -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)) + +} \ No newline at end of file diff --git a/rest_api/api/src/rt/auth/Login.go b/rest_api/api/src/rt/auth/Login.go new file mode 100644 index 0000000..a01f131 --- /dev/null +++ b/rest_api/api/src/rt/auth/Login.go @@ -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 +} diff --git a/rest_api/api/src/rt/auth/Registr.go b/rest_api/api/src/rt/auth/Registr.go new file mode 100644 index 0000000..babbd58 --- /dev/null +++ b/rest_api/api/src/rt/auth/Registr.go @@ -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 +} diff --git a/rest_api/api/src/rt/auth/authAdminMiddlware.go b/rest_api/api/src/rt/auth/authAdminMiddlware.go new file mode 100644 index 0000000..e4a049c --- /dev/null +++ b/rest_api/api/src/rt/auth/authAdminMiddlware.go @@ -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)) + }) +} diff --git a/rest_api/api/src/rt/auth/authMiddleware.go b/rest_api/api/src/rt/auth/authMiddleware.go new file mode 100644 index 0000000..b8c75fc --- /dev/null +++ b/rest_api/api/src/rt/auth/authMiddleware.go @@ -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)) + }) +} diff --git a/rest_api/api/src/rt/auth/auth_test.go b/rest_api/api/src/rt/auth/auth_test.go new file mode 100644 index 0000000..6232c1d --- /dev/null +++ b/rest_api/api/src/rt/auth/auth_test.go @@ -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) + } +} diff --git a/rest_api/api/src/rt/prf/AuthUserMiddleWare.go b/rest_api/api/src/rt/prf/AuthUserMiddleWare.go new file mode 100644 index 0000000..af24572 --- /dev/null +++ b/rest_api/api/src/rt/prf/AuthUserMiddleWare.go @@ -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) + }) +} \ No newline at end of file diff --git a/rest_api/api/src/rt/prf/profile.go b/rest_api/api/src/rt/prf/profile.go new file mode 100644 index 0000000..9cd63ce --- /dev/null +++ b/rest_api/api/src/rt/prf/profile.go @@ -0,0 +1,7 @@ +package prf + +import "net/http" + +func Profile(w http.ResponseWriter, r *http.Request) { + +} \ No newline at end of file diff --git a/rest_api/api/src/rt/srch/search.go b/rest_api/api/src/rt/srch/search.go new file mode 100644 index 0000000..2e1f324 --- /dev/null +++ b/rest_api/api/src/rt/srch/search.go @@ -0,0 +1,7 @@ +package srch + +import "net/http" + +func Search(w http.ResponseWriter, r *http.Request) { + +} diff --git a/rest_api/api/src/storages/psql/psql.go b/rest_api/api/src/storages/psql/psql.go new file mode 100644 index 0000000..780a042 --- /dev/null +++ b/rest_api/api/src/storages/psql/psql.go @@ -0,0 +1,5 @@ +package psql + +import "gorm.io/gorm" + +var PSQL_GORM_DB *gorm.DB diff --git a/rest_api/docker-compose.yml b/rest_api/docker-compose.yml new file mode 100644 index 0000000..9ba6863 --- /dev/null +++ b/rest_api/docker-compose.yml @@ -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: + + + \ No newline at end of file