controller added

Registrierung hinzugefügt
This commit is contained in:
2023-11-12 20:28:09 +01:00
parent d2cd4c3a41
commit 7c3d3e03bc
13 changed files with 429 additions and 30 deletions

View File

@@ -4,12 +4,11 @@ import (
"fmt" "fmt"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"golang.org/x/crypto/bcrypt"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"moretcgshop/app/models"
"os"
"gorm.io/gorm" "gorm.io/gorm"
"log" "log"
"moretcgshop/app/models"
"net/http" "net/http"
) )
@@ -35,16 +34,49 @@ type DBConfig struct {
DBDriver string DBDriver string
} }
var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY"))) var store = sessions.NewCookieStore([]byte("DamianFinja")) //os.Getenv("SESSION_KEY")))
var sessionShoppingCart = "shopping-cart-session" var sessionShoppingCart = "shopping-cart-session"
var sessionFlash = "flash-session" var sessionFlash = "flash-session"
var sessionUser = "user-session" var sessionUser = "user-session"
func (server *Server) Initialize(appConfig AppConfig, dbConfig DBConfig) { func (server *Server) Initialize(appConfig AppConfig, dbConfig DBConfig) {
fmt.Println("Willkommen zu " + appConfig.AppName) fmt.Println("Willkommen zu " + appConfig.AppName)
//server.initializeDB(dbConfig) server.initializeDB(dbConfig)
server.initializeAppConfig(appConfig) server.initializeAppConfig(appConfig)
server.initializeRoutes() server.routeInit()
}
func SetFlash(w http.ResponseWriter, r *http.Request, name string, value string) {
session, err := store.Get(r, sessionFlash)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
session.AddFlash(value, name)
err = session.Save(r, w)
if err != nil {
fmt.Println(err.Error())
}
}
func GetFlash(w http.ResponseWriter, r *http.Request, name string) []string {
session, err := store.Get(r, sessionFlash)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return nil
}
fm := session.Flashes(name)
if len(fm) < 0 {
return nil
}
session.Save(r, w)
var flashes []string
for _, fl := range fm {
flashes = append(flashes, fl.(string))
}
return flashes
} }
func (server *Server) Run(addr string) { func (server *Server) Run(addr string) {
@@ -56,6 +88,15 @@ func (s Server) InitCommands(config AppConfig, config2 DBConfig) {
} }
func MakePassword(password string) (string, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
return string(hashedPassword), err
}
func ComparePassword(password string, hashedPassword string) bool {
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) == nil
}
func (server *Server) initializeDB(dbConfig DBConfig) { func (server *Server) initializeDB(dbConfig DBConfig) {
var err error var err error
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", dbConfig.DBHost, dbConfig.DBUser, dbConfig.DBPassword, dbConfig.DBName, dbConfig.DBPort) dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", dbConfig.DBHost, dbConfig.DBUser, dbConfig.DBPassword, dbConfig.DBName, dbConfig.DBPort)
@@ -63,9 +104,10 @@ func (server *Server) initializeDB(dbConfig DBConfig) {
if err != nil { if err != nil {
panic("Failed on connecting to the database server") panic("Failed on connecting to the database server")
} }
server.dbMigrate()
} }
func (server *Server) dbMigrate() { func (server *Server) dbMigrate() {
/*for _, model := range models.RegisterModels() { for _, model := range models.RegisterModels() {
err := server.DB.Debug().AutoMigrate(model.Model) err := server.DB.Debug().AutoMigrate(model.Model)
if err != nil { if err != nil {
@@ -74,8 +116,6 @@ func (server *Server) dbMigrate() {
} }
fmt.Println("Database migrated successfully.") fmt.Println("Database migrated successfully.")
*/
} }
func (server *Server) initializeAppConfig(config AppConfig) { func (server *Server) initializeAppConfig(config AppConfig) {
@@ -108,3 +148,19 @@ func (server *Server) CurrentUser(w http.ResponseWriter, r *http.Request) *model
return user return user
} }
func (server *Server) routeInit() {
server.Router = mux.NewRouter()
server.Router.HandleFunc("/", server.Home).Methods("GET")
server.Router.HandleFunc("/login", server.Login).Methods("GET")
server.Router.HandleFunc("/login", server.DoLogin).Methods("POST")
server.Router.HandleFunc("/register", server.Register).Methods("GET")
server.Router.HandleFunc("/register", server.DoRegister).Methods("POST")
server.Router.HandleFunc("/logout", server.Logout).Methods("GET")
staticFileDirectory := http.Dir("./assets/")
staticFileHandler := http.StripPrefix("/public/", http.FileServer(staticFileDirectory))
server.Router.PathPrefix("/public/").Handler(staticFileHandler).Methods("GET")
}

View File

@@ -1,15 +0,0 @@
package controllers
import (
"github.com/gorilla/mux"
"net/http"
)
func (server *Server) initializeRoutes() {
server.Router = mux.NewRouter()
server.Router.HandleFunc("/", server.Home).Methods("GET")
staticFileDirectory := http.Dir("./assets/")
staticFileHandler := http.StripPrefix("/public/", http.FileServer(staticFileDirectory))
server.Router.PathPrefix("/public/").Handler(staticFileHandler).Methods("GET")
}

View File

@@ -0,0 +1,115 @@
package controllers
import (
"github.com/google/uuid"
"github.com/unrolled/render"
"moretcgshop/app/models"
"net/http"
)
func (server *Server) Login(w http.ResponseWriter, r *http.Request) {
renderer := render.New(render.Options{
Layout: "layout",
Extensions: []string{".html", ".tmpl"},
})
_ = renderer.HTML(w, http.StatusOK, "login", map[string]interface{}{
"error": GetFlash(w, r, "error"),
})
}
func (server *Server) DoLogin(w http.ResponseWriter, r *http.Request) {
email := r.FormValue("email")
password := r.FormValue("password")
userModel := models.User{}
user, err := userModel.FindByEmail(server.DB, email)
if err != nil {
SetFlash(w, r, "error", "Email oder Password sind nicht korrekt")
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
if !ComparePassword(password, user.Password) {
SetFlash(w, r, "error", "Email oder Password sind nicht korrekt")
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
session, _ := store.Get(r, sessionUser)
session.Values["id"] = user.ID
session.Save(r, w)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (server *Server) Register(w http.ResponseWriter, r *http.Request) {
renderer := render.New(render.Options{
Layout: "layout",
Extensions: []string{".html", ",tmpl"},
})
_ = renderer.HTML(w, http.StatusOK, "register", map[string]interface{}{
"error": GetFlash(w, r, "error"),
})
}
func (server *Server) DoRegister(w http.ResponseWriter, r *http.Request) {
firstName := r.FormValue("first_name")
lastName := r.FormValue("last_name")
email := r.FormValue("email")
password := r.FormValue("password")
password2 := r.FormValue("password_repeat")
if firstName == "" || lastName == "" || email == "" || password == "" || password2 == "" {
SetFlash(w, r, "error", "First name, last name, email and password are required!")
http.Redirect(w, r, "/register", http.StatusSeeOther)
return
}
userModel := models.User{}
existUser, _ := userModel.FindByEmail(server.DB, email)
if existUser != nil {
SetFlash(w, r, "error", "Sorry, diese E-Mail wurde bereits registriert")
http.Redirect(w, r, "/register", http.StatusSeeOther)
return
}
if password != password2 {
SetFlash(w, r, "error", "Passwörter stimmen nicht überein")
http.Redirect(w, r, "/register", http.StatusSeeOther)
return
}
hashedPassword, _ := MakePassword(password)
params := &models.User{
ID: uuid.New().String(),
FirstName: firstName,
LastName: lastName,
Email: email,
Password: hashedPassword,
}
user, err := userModel.CreateUser(server.DB, params)
if err != nil {
SetFlash(w, r, "error", "Sorry Registrierung war nicht erfolgreich")
http.Redirect(w, r, "/register", http.StatusSeeOther)
return
}
session, _ := store.Get(r, sessionUser)
session.Values["id"] = user.ID
session.Save(r, w)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (server *Server) Logout(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, sessionUser)
session.Values["id"] = nil
session.Save(r, w)
http.Redirect(w, r, "/", http.StatusSeeOther)
}

14
app/models/Category.go Normal file
View File

@@ -0,0 +1,14 @@
package models
import "time"
type Category struct {
ID string
ParentID string
Section Section
SectionID string
Products []Product `gorm:"many2many:product_categories;"`
Name string
CreatedAt time.Time
UpdatedAt time.Time
}

11
app/models/Section.go Normal file
View File

@@ -0,0 +1,11 @@
package models
import "time"
type Section struct {
ID string
Name string
CreatedAt time.Time
UpdatedAt time.Time
Categories []Category
}

14
app/models/models.go Normal file
View File

@@ -0,0 +1,14 @@
package models
type Model struct {
Model interface{}
}
func RegisterModels() []Model {
return []Model{
{Model: User{}},
{Model: Product{}},
{Model: Category{}},
{Model: Section{}},
}
}

16
app/models/product.go Normal file
View File

@@ -0,0 +1,16 @@
package models
import (
"gorm.io/gorm"
"time"
)
type Product struct {
ID string
ParentID string
Name string
Categories []Category `gorm:"many2many:product_categories;"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt
}

View File

@@ -2,6 +2,7 @@ package models
import ( import (
"gorm.io/gorm" "gorm.io/gorm"
"strings"
"time" "time"
) )
@@ -19,9 +20,7 @@ type User struct {
} }
func (u *User) FindByID(db *gorm.DB, userID string) (*User, error) { func (u *User) FindByID(db *gorm.DB, userID string) (*User, error) {
var user User var user User
err := db.Debug().Model(User{}).Where("id = ?", userID). err := db.Debug().Model(User{}).Where("id = ?", userID).
First(&user).Error First(&user).Error
if err != nil { if err != nil {
@@ -29,3 +28,29 @@ func (u *User) FindByID(db *gorm.DB, userID string) (*User, error) {
} }
return &user, nil return &user, nil
} }
func (u *User) FindByEmail(db *gorm.DB, email string) (*User, error) {
var user User
err := db.Debug().Model(User{}).Where("LOWER(email) = ?", strings.ToLower(email)).
First(&user).Error
if err != nil {
return nil, err
}
return &user, nil
}
func (u *User) CreateUser(db *gorm.DB, param *User) (*User, error) {
user := &User{
ID: param.ID,
FirstName: param.FirstName,
LastName: param.LastName,
Email: param.Email,
Password: param.Password,
}
err := db.Debug().Create(&user).Error
if err != nil {
return nil, err
}
return user, nil
}

View File

@@ -31,9 +31,9 @@ func Run() {
appConfig.AppURL = getEnv("APP_URL", "http://localhost:9000") appConfig.AppURL = getEnv("APP_URL", "http://localhost:9000")
dbConfig.DBHost = getEnv("DB_HOST", "localhost") dbConfig.DBHost = getEnv("DB_HOST", "localhost")
dbConfig.DBUser = getEnv("DB_USER", "user") dbConfig.DBUser = getEnv("DB_USER", "moretcg")
dbConfig.DBPassword = getEnv("DB_PASSWORD", "password") dbConfig.DBPassword = getEnv("DB_PASSWORD", "moretcg")
dbConfig.DBName = getEnv("DB_NAME", "dbname") dbConfig.DBName = getEnv("DB_NAME", "moretcg")
dbConfig.DBPort = getEnv("DB_PORT", "5432") dbConfig.DBPort = getEnv("DB_PORT", "5432")
dbConfig.DBDriver = getEnv("DB_DRIVER", "postgres") dbConfig.DBDriver = getEnv("DB_DRIVER", "postgres")

3
go.mod
View File

@@ -3,10 +3,12 @@ module moretcgshop
go 1.20 go 1.20
require ( require (
github.com/google/uuid v1.4.0
github.com/gorilla/mux v1.8.1 github.com/gorilla/mux v1.8.1
github.com/gorilla/sessions v1.2.2 github.com/gorilla/sessions v1.2.2
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/unrolled/render v1.6.1 github.com/unrolled/render v1.6.1
golang.org/x/crypto v0.14.0
gorm.io/driver/postgres v1.5.4 gorm.io/driver/postgres v1.5.4
gorm.io/gorm v1.25.5 gorm.io/gorm v1.25.5
) )
@@ -19,7 +21,6 @@ require (
github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/sys v0.13.0 // indirect golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect
) )

2
go.sum
View File

@@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=

View File

@@ -0,0 +1,76 @@
{{ define "login" }}
<section class="breadcrumb-section pb-3 pt-3">
<div class="container">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Login</li>
</ol>
</div>
</section>
<div class="container pt-lg-7 pb-lg-7">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card bg-secondary shadow border-0">
<!--<div class="card-header bg-white pb-5">
<div class="text-muted text-center mb-3"><small>Sign in with</small></div>
<div class="btn-wrapper text-center">
<a href="#" class="btn btn-neutral btn-icon">
<span class="btn-inner--icon"><img src="/public/img/icons/common/github.svg"></span>
<span class="btn-inner--text">Github</span>
</a>
<a href="#" class="btn btn-neutral btn-icon">
<span class="btn-inner--icon"><img src="/public/img/icons/common/google.svg"></span>
<span class="btn-inner--text">Google</span>
</a>
</div>
</div>-->
<div class="card-body px-lg-5 py-lg-5">
<div class="text-center text-muted mb-4">
<small>Login</small>
</div>
{{ if .error }}
<div class="alert alert-warning">
{{ range $i, $msg := .error }}
{{ $msg }}<br/>
{{ end }}
</div>
{{ end }}
<form role="form" action="/login" method="POST">
<div class="form-group mb-3">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-email-83"></i></span>
</div>
<input class="form-control" name="email" placeholder="Email" type="email">
</div>
</div>
<div class="form-group focused">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-lock-circle-open"></i></span>
</div>
<input class="form-control" name="password" placeholder="Password" type="password">
</div>
</div>
<!--<div class="custom-control custom-control-alternative custom-checkbox">
<input class="custom-control-input" id=" customCheckLogin" type="checkbox">
<label class="custom-control-label" for=" customCheckLogin"><span>Remember me</span></label>
</div>-->
<div class="text-center">
<button type="submit" class="btn btn-primary my-4">Login</button>
</div>
</form>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<a href="#" class="text-light"><small>Password Vergessen</small></a>
</div>
<div class="col-6 text-right">
<a href="#" class="text-light"><small>Neue Account Registrieren</small></a>
</div>
</div>
</div>
</div>
</div>
{{ end }}

View File

@@ -0,0 +1,84 @@
{{ define "register" }}
<section class="breadcrumb-section pb-3 pt-3">
<div class="container">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Registrieren</li>
</ol>
</div>
</section>
<div class="container pt-lg-7 pb-lg-7">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card bg-secondary shadow border-0">
<div class="card-header bg-white pb-5">
<div class="text-muted text-center mb-3"><small>Neue Account erstellen</small></div>
</div>
<div class="card-body px-lg-5 py-lg-5">
<!--<div class="text-center text-muted mb-4">
<small>Or sign in with credentials</small>
</div>-->
{{ if .error }}
<div class="alert alert-warning">
{{ range $i, $msg := .error }}
{{ $msg }}<br/>
{{ end }}
</div>
{{ end }}
<form role="form" action="/register" method="POST">
<div class="form-group mb-3">
<div class="input-group input-group-alternative">
<input class="form-control" name="first_name" placeholder="Vorname" type="text">
</div>
</div>
<div class="form-group mb-3">
<div class="input-group input-group-alternative">
<input class="form-control" name="last_name" placeholder="Nachname" type="text">
</div>
</div>
<div class="form-group mb-3">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-email-83"></i></span>
</div>
<input class="form-control" name="email" placeholder="Email" type="email">
</div>
</div>
<div class="form-group focused">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-lock-circle-open"></i></span>
</div>
<input class="form-control" name="password" placeholder="Password" type="password">
</div>
</div>
<div class="form-group focused">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ni ni-lock-circle-open"></i></span>
</div>
<input class="form-control" name="password_repeat" placeholder="Password Wiederholen" type="password">
</div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary my-4">Registrieren</button>
</div>
</form>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<a href="#" class="text-light"><small>Password vergessen?</small></a>
</div>
<!--<div class="col-6 text-right">
<a href="#" class="text-light"><small>Create new account</small></a>
</div>-->
</div>
</div>
</div>
</div>
{{ end }}