controller added
Registrierung hinzugefügt
This commit is contained in:
@@ -4,12 +4,11 @@ import (
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/driver/postgres"
|
||||
"moretcgshop/app/models"
|
||||
"os"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"moretcgshop/app/models"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -35,16 +34,49 @@ type DBConfig struct {
|
||||
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 sessionFlash = "flash-session"
|
||||
var sessionUser = "user-session"
|
||||
|
||||
func (server *Server) Initialize(appConfig AppConfig, dbConfig DBConfig) {
|
||||
fmt.Println("Willkommen zu " + appConfig.AppName)
|
||||
//server.initializeDB(dbConfig)
|
||||
server.initializeDB(dbConfig)
|
||||
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) {
|
||||
@@ -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) {
|
||||
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)
|
||||
@@ -63,9 +104,10 @@ func (server *Server) initializeDB(dbConfig DBConfig) {
|
||||
if err != nil {
|
||||
panic("Failed on connecting to the database server")
|
||||
}
|
||||
server.dbMigrate()
|
||||
}
|
||||
func (server *Server) dbMigrate() {
|
||||
/*for _, model := range models.RegisterModels() {
|
||||
for _, model := range models.RegisterModels() {
|
||||
err := server.DB.Debug().AutoMigrate(model.Model)
|
||||
|
||||
if err != nil {
|
||||
@@ -74,8 +116,6 @@ func (server *Server) dbMigrate() {
|
||||
}
|
||||
|
||||
fmt.Println("Database migrated successfully.")
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
func (server *Server) initializeAppConfig(config AppConfig) {
|
||||
@@ -108,3 +148,19 @@ func (server *Server) CurrentUser(w http.ResponseWriter, r *http.Request) *model
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
115
app/controllers/user_controller.go
Normal file
115
app/controllers/user_controller.go
Normal 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
14
app/models/Category.go
Normal 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
11
app/models/Section.go
Normal 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
14
app/models/models.go
Normal 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
16
app/models/product.go
Normal 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
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -19,9 +20,7 @@ type User struct {
|
||||
}
|
||||
|
||||
func (u *User) FindByID(db *gorm.DB, userID string) (*User, error) {
|
||||
|
||||
var user User
|
||||
|
||||
err := db.Debug().Model(User{}).Where("id = ?", userID).
|
||||
First(&user).Error
|
||||
if err != nil {
|
||||
@@ -29,3 +28,29 @@ func (u *User) FindByID(db *gorm.DB, userID string) (*User, error) {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ func Run() {
|
||||
appConfig.AppURL = getEnv("APP_URL", "http://localhost:9000")
|
||||
|
||||
dbConfig.DBHost = getEnv("DB_HOST", "localhost")
|
||||
dbConfig.DBUser = getEnv("DB_USER", "user")
|
||||
dbConfig.DBPassword = getEnv("DB_PASSWORD", "password")
|
||||
dbConfig.DBName = getEnv("DB_NAME", "dbname")
|
||||
dbConfig.DBUser = getEnv("DB_USER", "moretcg")
|
||||
dbConfig.DBPassword = getEnv("DB_PASSWORD", "moretcg")
|
||||
dbConfig.DBName = getEnv("DB_NAME", "moretcg")
|
||||
dbConfig.DBPort = getEnv("DB_PORT", "5432")
|
||||
dbConfig.DBDriver = getEnv("DB_DRIVER", "postgres")
|
||||
|
||||
|
||||
3
go.mod
3
go.mod
@@ -3,10 +3,12 @@ module moretcgshop
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.4.0
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/unrolled/render v1.6.1
|
||||
golang.org/x/crypto v0.14.0
|
||||
gorm.io/driver/postgres v1.5.4
|
||||
gorm.io/gorm v1.25.5
|
||||
)
|
||||
@@ -19,7 +21,6 @@ require (
|
||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // 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/text v0.13.0 // indirect
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -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/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
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/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
|
||||
76
templates/pages/login.html
Normal file
76
templates/pages/login.html
Normal 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 }}
|
||||
84
templates/pages/register.html
Normal file
84
templates/pages/register.html
Normal 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 }}
|
||||
Reference in New Issue
Block a user