Add token repositorie

This commit is contained in:
2025-04-14 23:29:24 +02:00
parent cca0b2775c
commit 6d63e53200
6 changed files with 163 additions and 30 deletions

View File

@@ -1,8 +1,6 @@
package controllers package controllers
import ( import (
"crypto/rand"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
@@ -15,6 +13,7 @@ import (
"git.dynamicdiscord.de/kalipso/zineshop/models" "git.dynamicdiscord.de/kalipso/zineshop/models"
//"git.dynamicdiscord.de/kalipso/zineshop/services" //"git.dynamicdiscord.de/kalipso/zineshop/services"
"git.dynamicdiscord.de/kalipso/zineshop/repositories" "git.dynamicdiscord.de/kalipso/zineshop/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/utils"
) )
type CartItemController interface { type CartItemController interface {
@@ -53,15 +52,6 @@ func getSetCookieValue(c *gin.Context, cookieName string) string {
return "" // Return empty string if cookie is not found return "" // Return empty string if cookie is not found
} }
func generateSessionId(length int) string {
bytes := make([]byte, length) // 16 bytes = 128 bits
_, err := rand.Read(bytes)
if err != nil {
panic("failed to generate session ID")
}
return hex.EncodeToString(bytes)
}
func GetSessionId(ctx *gin.Context) string { func GetSessionId(ctx *gin.Context) string {
sessionId, err := ctx.Cookie("session_id") sessionId, err := ctx.Cookie("session_id")
@@ -73,17 +63,13 @@ func GetSessionId(ctx *gin.Context) string {
return responseCookie return responseCookie
} }
sessionId = generateSessionId(16) sessionId = utils.GenerateSessionId(16)
ctx.SetCookie("session_id", sessionId, 3600, "/", "", false, true) ctx.SetCookie("session_id", sessionId, 3600, "/", "", false, true)
} }
return sessionId return sessionId
} }
func GenerateToken() string {
return generateSessionId(16)
}
func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.CartItem, error) { func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.CartItem, error) {
sessionId := GetSessionId(ctx) sessionId := GetSessionId(ctx)
shopItemIdStr := ctx.PostForm("ShopItemId") shopItemIdStr := ctx.PostForm("ShopItemId")
@@ -162,7 +148,7 @@ func (rc *cartItemController) NewAddressFromForm(ctx *gin.Context) (models.Addre
func (rc *cartItemController) NewOrderFromForm(ctx *gin.Context) (models.Order, error) { func (rc *cartItemController) NewOrderFromForm(ctx *gin.Context) (models.Order, error) {
sessionId := GetSessionId(ctx) sessionId := GetSessionId(ctx)
status := models.OrderStatus("AwaitingConfirmation") status := models.OrderStatus("AwaitingConfirmation")
token := GenerateToken() token := utils.GenerateToken()
email := ctx.PostForm("email") email := ctx.PostForm("email")
comment := ctx.PostForm("comment") comment := ctx.PostForm("comment")
firstName := ctx.PostForm("firstName") firstName := ctx.PostForm("firstName")

View File

@@ -35,7 +35,7 @@ func (uc *UserController) Register(c *gin.Context) {
return return
} }
_, err = services.Users.Register(body.Name, body.Email, body.Password) _, err = services.Users.Register(body.Name, body.Email, body.Password, false)
if err != nil { if err != nil {
fmt.Println("Error: ", err) fmt.Println("Error: ", err)
@@ -152,18 +152,75 @@ func (rc *UserController) RegisterHandler(c *gin.Context) {
email := c.PostForm("email") email := c.PostForm("email")
password := c.PostForm("password") password := c.PostForm("password")
_, err := services.Users.Register(name, email, password) //first registered user is admin
isEmpty, _ := repositories.Users.IsEmpty()
if isEmpty {
_, err := services.Users.Register(name, email, password, true)
if err != nil {
data := gin.H{
"error": "Registering Failed.",
"success": "",
}
c.HTML(http.StatusOK, "register.html", data)
return
}
data := gin.H{
"error": "",
"success": "You successfully registered as Admin. Try logging in.",
}
c.HTML(http.StatusOK, "register.html", data)
return
}
//for any other user token is required
token := c.PostForm("token")
if token == "" {
data := gin.H{
"error": "No token. No register.",
"success": "",
}
c.HTML(http.StatusOK, "register.html", data)
}
tokenExists, err := repositories.Tokens.Exists(token)
if err != nil {
data := gin.H{
"error": err,
"success": "",
}
c.HTML(http.StatusOK, "register.html", data)
}
if !tokenExists {
data := gin.H{
"error": "Invalid Token.",
"success": "",
}
c.HTML(http.StatusOK, "register.html", data)
}
_, err = services.Users.Register(name, email, password, false)
if err != nil { if err != nil {
data := gin.H{ data := gin.H{
"error": "Registering Failed.", "error": "Registering Failed.",
"success": "", "success": "",
} }
c.HTML(http.StatusOK, "register.html", data) c.HTML(http.StatusOK, "register.html", data)
return return
} }
err = repositories.Tokens.Delete(token)
if err != nil {
fmt.Println("Could not delete RegisterToken: ", err)
}
data := gin.H{ data := gin.H{
"error": "", "error": "",
"success": "You successfully registered. Try logging in.", "success": "You successfully registered. Try logging in.",

View File

@@ -4,9 +4,15 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type RegisterToken struct {
gorm.Model
Token string `json:"token" binding:"required" gorm:"unique;not null"`
}
type User struct { type User struct {
gorm.Model gorm.Model
Name string `json:"name" binding:"required" gorm:"unique;not null"` Name string `json:"name" binding:"required" gorm:"unique;not null"`
Password string `json:"password" binding:"required" gorm:"not null"` Password string `json:"password" binding:"required" gorm:"not null"`
Email string `json:"email" binding:"required,email" gorm:"unique;not null"` Email string `json:"email" binding:"required,email" gorm:"unique;not null"`
IsAdmin bool `json:"isAdmin" gorm:"default:false;not null"`
} }

View File

@@ -0,0 +1,81 @@
package repositories
import (
"fmt"
"gorm.io/gorm"
"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/utils"
)
type RegisterTokenRepository interface {
Create() (models.RegisterToken, error)
GetAll() ([]models.RegisterToken, error)
Exists(string) (bool, error)
Delete(string) error
}
type GORMRegisterTokenRepository struct {
DB *gorm.DB
}
func NewGORMRegisterTokenRepository(db *gorm.DB) RegisterTokenRepository {
return &GORMRegisterTokenRepository{
DB: db,
}
}
func (t *GORMRegisterTokenRepository) Create() (models.RegisterToken, error) {
token := utils.GenerateToken()
exists, err := t.Exists(token)
if err != nil {
return models.RegisterToken{}, err
}
if exists {
return t.Create()
}
newToken := models.RegisterToken{
Token: token,
}
result := t.DB.Create(&newToken)
if result.Error != nil {
return models.RegisterToken{}, result.Error
}
return newToken, nil
}
func (t *GORMRegisterTokenRepository) GetAll() ([]models.RegisterToken, error) {
var tokens []models.RegisterToken
result := t.DB.Find(&tokens)
return tokens, result.Error
}
func (t *GORMRegisterTokenRepository) Exists(tokenString string) (bool, error) {
var token models.RegisterToken
result := t.DB.First(&token, tokenString)
if result.Error != nil {
return false, result.Error
}
return true, nil
}
func (t *GORMRegisterTokenRepository) Delete(token string) error {
result := t.DB.Where("token = ?", token).Delete(&models.RegisterToken{})
if result.Error != nil {
return result.Error
} else if result.RowsAffected == 0 {
return fmt.Errorf("Token not found, could not be deleted")
}
return nil
}

View File

@@ -14,6 +14,7 @@ var (
Tags TagRepository Tags TagRepository
CartItems CartItemRepository CartItems CartItemRepository
Orders OrderRepository Orders OrderRepository
Tokens RegisterTokenRepository
) )
func InitRepositories() { func InitRepositories() {
@@ -27,7 +28,8 @@ func InitRepositories() {
&models.User{}, &models.User{},
&models.Tag{}, &models.Tag{},
&models.CartItem{}, &models.CartItem{},
&models.Order{}) &models.Order{},
&models.RegisterToken{})
if err != nil { if err != nil {
panic("failed to migrate database") panic("failed to migrate database")
@@ -38,4 +40,5 @@ func InitRepositories() {
Tags = NewGORMTagRepository(db) Tags = NewGORMTagRepository(db)
CartItems = NewGORMCartItemRepository(db) CartItems = NewGORMCartItemRepository(db)
Orders = NewGORMOrderRepository(db) Orders = NewGORMOrderRepository(db)
Tokens = NewGORMRegisterTokenRepository(db)
} }

View File

@@ -1,9 +1,9 @@
package services package services
import( import (
"golang.org/x/crypto/bcrypt"
"os" "os"
"time" "time"
"golang.org/x/crypto/bcrypt"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
@@ -11,13 +11,13 @@ import(
"git.dynamicdiscord.de/kalipso/zineshop/repositories" "git.dynamicdiscord.de/kalipso/zineshop/repositories"
) )
var( var (
Users UserService = UserService{} Users UserService = UserService{}
) )
type UserService struct {} type UserService struct{}
func (u *UserService) Register(name string, email string, password string) (models.User, error) { func (u *UserService) Register(name string, email string, password string, isAdmin bool) (models.User, error) {
//hash pw //hash pw
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10) hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
@@ -25,7 +25,7 @@ func (u *UserService) Register(name string, email string, password string) (mode
return models.User{}, err return models.User{}, err
} }
user := models.User{Name: name, Email: email, Password: string(hash)} user := models.User{Name: name, Email: email, Password: string(hash), IsAdmin: isAdmin}
_, err = repositories.Users.Create(user) _, err = repositories.Users.Create(user)
if err != nil { if err != nil {
@@ -35,7 +35,7 @@ func (u *UserService) Register(name string, email string, password string) (mode
return user, nil return user, nil
} }
//return jwt tokenstring on success // return jwt tokenstring on success
func (u *UserService) Login(email string, password string) (string, error) { func (u *UserService) Login(email string, password string) (string, error) {
//lookup requested user //lookup requested user
user, err := repositories.Users.GetByEmail(email) user, err := repositories.Users.GetByEmail(email)