shopitems instead rooms

This commit is contained in:
2025-03-02 18:49:36 +01:00
parent 48491d0786
commit 6398429c92
11 changed files with 409 additions and 438 deletions

View File

@@ -1,187 +0,0 @@
package controllers
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
)
type CRUDController interface {
Create(*gin.Context)
GetAll(*gin.Context)
GetById(*gin.Context)
Update(*gin.Context)
Delete(*gin.Context)
}
type RoomController interface {
CRUDController
GetUsers(*gin.Context)
AddUser(*gin.Context)
}
type roomController struct {}
func NewRoomController() RoomController {
return &roomController{}
}
func (rc *roomController) GetAll(c *gin.Context) {
rooms, err := repositories.Rooms.GetAll()
if err != nil {
ReplyError(c, fmt.Errorf("Could not query rooms"))
return
}
c.JSON(http.StatusOK, rooms)
}
func (rc *roomController) GetById(c *gin.Context) {
room, err := repositories.Rooms.GetById(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("Could not query room: %v", err))
return
}
ReplyOK(c, room)
}
func (rc *roomController) Create(c *gin.Context) {
user, exists := c.Get("user")
if !exists {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
room, err := models.NewRoom(c)
room.Admins = append(room.Admins, user.(models.User))
if err != nil {
ReplyError(c, err)
}
_, err = repositories.Rooms.Create(room)
if err != nil {
ReplyError(c, fmt.Errorf("Room creation failed: %s", err))
return
}
//userID := user.(models.User).ID
//rc.DB.Model(&models.Room{}).Where("id = ?"), room.ID).Association("Admins").Append(&models.User{ID: userID})
//if result.Error != nil {
// ReplyError(c, fmt.Errorf("Room creation failed: %s", result.Error))
// return
//}
ReplyOK(c, "Room was created")
}
func (rc *roomController) Update(c *gin.Context) {
roomId, err := strconv.Atoi(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("Room with Id '%s' does not exist", c.Param("id")))
return
}
room, err := models.NewRoom(c)
if err != nil {
ReplyError(c, err)
return
}
room.ID = uint(roomId)
_, err = repositories.Rooms.Update(room)
if err != nil {
ReplyError(c, fmt.Errorf("Room creation failed: %s", err))
return
}
ReplyOK(c, "Room was updated")
}
func (rc *roomController) Delete(c *gin.Context) {
err := repositories.Rooms.DeleteById(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("Room deletion failed: %s", err))
return
}
ReplyOK(c, "Room was deleted")
}
func (rc *roomController) GetUsers(c *gin.Context) {
//only allow room admin
users, err := repositories.Rooms.GetRoomUsersById(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("Could not get users for room '%s'", c.Param("id")))
return
}
var emails []string
for _, user := range users {
emails = append(emails, user.Email)
}
ReplyOK(c, emails)
}
func (rc *roomController) AddUser(c *gin.Context) {
//only allow room admin
var body struct {
Email string
}
err := c.Bind(&body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to read body",
})
return
}
//lookup requested user
user, err := repositories.Users.GetByEmail(body.Email)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid user",
})
return
}
err = repositories.Rooms.AddRoomUserById(c.Param("id"), user)
if err != nil {
ReplyError(c, fmt.Errorf("Could not add user to room."))
return
}
ReplyOK(c, "Added User to Room")
}
func ReplyError(ctx *gin.Context, err error) {
ctx.JSON(http.StatusBadRequest, gin.H{ "error": err.Error() })
}
func ReplyOK(ctx *gin.Context, message any) {
ctx.JSON(http.StatusOK, message)
}

View File

@@ -0,0 +1,122 @@
package controllers
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
)
type CRUDController interface {
Create(*gin.Context)
GetAll(*gin.Context)
GetById(*gin.Context)
Update(*gin.Context)
Delete(*gin.Context)
}
type ShopItemController interface {
CRUDController
}
type shopItemController struct {}
func NewShopItemController() ShopItemController {
return &shopItemController{}
}
func (rc *shopItemController) GetAll(c *gin.Context) {
shopItems, err := repositories.ShopItems.GetAll()
if err != nil {
ReplyError(c, fmt.Errorf("Could not query shopItems"))
return
}
c.JSON(http.StatusOK, shopItems)
}
func (rc *shopItemController) GetById(c *gin.Context) {
shopItem, err := repositories.ShopItems.GetById(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("Could not query shopItem: %v", err))
return
}
ReplyOK(c, shopItem)
}
func (rc *shopItemController) Create(c *gin.Context) {
shopItem, err := models.NewShopItem(c)
if err != nil {
ReplyError(c, err)
}
_, err = repositories.ShopItems.Create(shopItem)
if err != nil {
ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err))
return
}
//userID := user.(models.User).ID
//rc.DB.Model(&models.shopItem{}).Where("id = ?"), room.ID).Association("Admins").Append(&models.User{ID: userID})
//if result.Error != nil {
// ReplyError(c, fmt.Errorf("shopItem creation failed: %s", result.Error))
// return
//}
ReplyOK(c, "shopItem was created")
}
func (rc *shopItemController) Update(c *gin.Context) {
shopItemId, err := strconv.Atoi(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("shopItem with Id '%s' does not exist", c.Param("id")))
return
}
shopItem, err := models.NewShopItem(c)
if err != nil {
ReplyError(c, err)
return
}
shopItem.ID = uint(shopItemId)
_, err = repositories.ShopItems.Update(shopItem)
if err != nil {
ReplyError(c, fmt.Errorf("shopItem creation failed: %s", err))
return
}
ReplyOK(c, "shopItem was updated")
}
func (rc *shopItemController) Delete(c *gin.Context) {
err := repositories.ShopItems.DeleteById(c.Param("id"))
if err != nil {
ReplyError(c, fmt.Errorf("shopItem deletion failed: %s", err))
return
}
ReplyOK(c, "shopItem was deleted")
}
func ReplyError(ctx *gin.Context, err error) {
ctx.JSON(http.StatusBadRequest, gin.H{ "error": err.Error() })
}
func ReplyOK(ctx *gin.Context, message any) {
ctx.JSON(http.StatusOK, message)
}

View File

@@ -3,6 +3,7 @@ package controllers
import(
"fmt"
"net/http"
"math/rand"
"github.com/gin-gonic/gin"
@@ -139,7 +140,7 @@ func (rc *UserController) LoginHandler(c *gin.Context) {
// send it back
//c.SetSameSite(http.SameSiteLaxMode)
c.SetCookie("Authorization", tokenString, 3600 * 24, "", "", false, true)
c.HTML(http.StatusPermanentRedirect, "index.html", CreateSessionData(c, gin.H{}))
c.HTML(http.StatusOK, "login.html", CreateSessionData(c, gin.H{}))
}
func CreateSessionData(c *gin.Context, extra any) gin.H {
@@ -187,30 +188,34 @@ func (rc *UserController) RegisterView(c *gin.Context) {
}
func (rc *UserController) ResetView(c *gin.Context) {
rooms, _ := repositories.Rooms.GetAll()
shopItems, _ := repositories.ShopItems.GetAll()
data := gin.H{
"title": "Room Page",
"rooms": rooms,
"title": "shopItem Page",
"shopItems": shopItems,
}
c.HTML(http.StatusOK, "passwordreset.html", data)
}
func (rc *UserController) ResetHandler(c *gin.Context) {
rooms, _ := repositories.Rooms.GetAll()
shopItems, _ := repositories.ShopItems.GetAll()
data := gin.H{
"title": "Room Page",
"rooms": rooms,
"title": "shopItem Page",
"shopItems": shopItems,
}
c.HTML(http.StatusOK, "passwordreset.html", data)
}
func (rc *UserController) MainView(c *gin.Context) {
shopItems, _ := repositories.ShopItems.GetAll()
fmt.Println(len(shopItems))
data := CreateSessionData(c, gin.H{
"title": "Room Page",
"title": "shopItem Page",
"shopItems": shopItems,
})
fmt.Println(data)
@@ -218,6 +223,69 @@ func (rc *UserController) MainView(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", data)
}
type booking struct {
Booked bool
}
type calendarbooking struct{
Time string
Bookings []booking
}
func (rc *UserController) CalendarView(c *gin.Context) {
shopItems, _ := repositories.ShopItems.GetAll()
fmt.Println(len(shopItems))
generateBookings := func(amountShopItems int) []calendarbooking {
var result []calendarbooking
time := 6;
for _ = range 18 {
book := calendarbooking{
Time: fmt.Sprintf("%d:00", time),
Bookings: []booking{},
}
for _ = range amountShopItems {
book.Bookings = append(book.Bookings, booking{ Booked: rand.Float32() < 0.5 })
}
time += 1
result = append(result, book)
}
return result
}
bookings := gin.H{
"head": []string{
"malobeo",
"hole of fame",
"BK",
"AZ Conni",
},
"bookings": generateBookings(4),
//"bookings": []calendarbooking{
// {
// Time: "10:00",
// Bookings: []booking{
// { Booked: true },
// { Booked: false },
// },
// },
//},
}
data := CreateSessionData(c, gin.H{
"title": "shopItem Page",
"bookings": bookings,
"shopItemcount": len(bookings["head"].([]string)) + 1,
})
fmt.Println(data)
c.HTML(http.StatusOK, "calendar.html", data)
}
func (rc *UserController) Logout(c *gin.Context) {
c.SetCookie("Authorization", "", -1, "", "", false, true)
c.HTML(http.StatusOK, "index.html", gin.H{})

16
main.go
View File

@@ -15,7 +15,7 @@ import(
)
var(
roomController controllers.RoomController = controllers.NewRoomController()
shopItemController controllers.ShopItemController = controllers.NewShopItemController()
userController controllers.UserController = controllers.UserController{}
authValidator middlewares.AuthValidator = middlewares.AuthValidator{}
)
@@ -57,14 +57,14 @@ func main() {
apiRoutes := server.Group("/api")
//apiRoutes.Use(middlewares.BasicAuth())
{
apiRoutes.POST("/rooms", authValidator.RequireAuth, roomController.Create)
apiRoutes.GET("/rooms", authValidator.OptionalAuth, roomController.GetAll)
apiRoutes.GET("/rooms/:id", authValidator.OptionalAuth, roomController.GetById)
apiRoutes.PUT("/rooms/:id", authValidator.RequireAuth, roomController.Update)
apiRoutes.DELETE("/rooms/:id", authValidator.RequireAuth, roomController.Delete)
apiRoutes.POST("/shopitems", authValidator.RequireAuth, shopItemController.Create)
apiRoutes.GET("/shopitems", authValidator.OptionalAuth, shopItemController.GetAll)
apiRoutes.GET("/shopitems/:id", authValidator.OptionalAuth, shopItemController.GetById)
apiRoutes.PUT("/shopitems/:id", authValidator.RequireAuth, shopItemController.Update)
apiRoutes.DELETE("/shopitems/:id", authValidator.RequireAuth, shopItemController.Delete)
apiRoutes.GET("/rooms/:id/users", authValidator.RequireAuth, authValidator.RequireRoomAdmin, roomController.GetUsers)
apiRoutes.POST("/rooms/:id/users", authValidator.RequireAuth, roomController.AddUser)
//apiRoutes.GET("/rooms/:id/users", authValidator.RequireAuth, authValidator.RequireRoomAdmin, shopItemController.GetUsers)
//apiRoutes.POST("/rooms/:id/users", authValidator.RequireAuth, shopItemController.AddUser)
apiRoutes.POST("/users/register", userController.Register)
apiRoutes.POST("/users/login", userController.Login)

View File

@@ -4,47 +4,47 @@ import(
"os"
"fmt"
"time"
"strconv"
//"strconv"
"net/http"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"example.com/gin/test/models"
//"example.com/gin/test/models"
"example.com/gin/test/repositories"
)
type AuthValidator struct {
}
func (av *AuthValidator) RequireRoomAdmin(c *gin.Context) {
user, exists := c.Get("user")
if !exists {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
roomId, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{ "message": fmt.Sprintf("Room with Id '%s' does not exist", c.Param("id"))})
return
}
rooms, err := repositories.Users.GetOwnedRooms(user.(models.User))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{ "message": "Could not querie owend rooms"})
return
}
for _, room := range rooms {
if room.ID == uint(roomId) {
c.Next()
return
}
}
c.AbortWithStatus(http.StatusUnauthorized)
}
//func (av *AuthValidator) RequireRoomAdmin(c *gin.Context) {
// user, exists := c.Get("user")
// if !exists {
// c.AbortWithStatus(http.StatusUnauthorized)
// return
// }
//
// roomId, err := strconv.Atoi(c.Param("id"))
// if err != nil {
// c.JSON(http.StatusBadRequest, gin.H{ "message": fmt.Sprintf("Room with Id '%s' does not exist", c.Param("id"))})
// return
// }
//
// rooms, err := repositories.Users.GetOwnedRooms(user.(models.User))
//
// if err != nil {
// c.JSON(http.StatusBadRequest, gin.H{ "message": "Could not querie owend rooms"})
// return
// }
//
// for _, room := range rooms {
// if room.ID == uint(roomId) {
// c.Next()
// return
// }
// }
//
// c.AbortWithStatus(http.StatusUnauthorized)
//}
func (av *AuthValidator) RequireAuth(c *gin.Context) {
// Get Cookie

View File

@@ -1,28 +0,0 @@
package models
import (
"gorm.io/gorm"
"github.com/gin-gonic/gin"
)
type Room struct {
gorm.Model
Name string `json:"name" binding:"required" gorm:"unique;not null"`
Address string `json:"address"`
Website string `json:"website"`
Capacity int `json:"capacity"`
IsPublic bool `json:"isPublic" gorm:"default:true"`
Admins []User `gorm:"many2many:room_admins;"`
Users []User `gorm:"many2many:room_users;"`
}
func NewRoom(ctx *gin.Context) (Room, error) {
var room Room
err := ctx.ShouldBindJSON(&room)
if err != nil {
return Room{}, err
}
return room, nil
}

26
models/shopItem.go Normal file
View File

@@ -0,0 +1,26 @@
package models
import (
"gorm.io/gorm"
"github.com/gin-gonic/gin"
)
type ShopItem struct {
gorm.Model
Name string `json:"name" binding:"required" gorm:"unique;not null"`
Description string `json:"description" binding:"required"`
Price float64 `json:"price" binding:"required"`
IsPublic bool `json:"isPublic" gorm:"default:true"`
//Images gin.multipart.FileHeader ``
}
func NewShopItem(ctx *gin.Context) (ShopItem, error) {
var shopItem ShopItem
err := ctx.ShouldBindJSON(&shopItem)
if err != nil {
return ShopItem{}, err
}
return shopItem, nil
}

View File

@@ -9,5 +9,4 @@ type User struct {
Name string `json:"name" binding:"required" gorm:"unique;not null"`
Password string `json:"password" binding:"required" gorm:"not null"`
Email string `json:"email" binding:"required,email" gorm:"unique;not null"`
OwnedRooms []Room `gorm:"many2many:room_admins;"`
}

View File

@@ -2,7 +2,6 @@ package repositories
import(
"os"
"strconv"
"gorm.io/gorm"
"gorm.io/driver/sqlite"
@@ -10,192 +9,21 @@ import(
)
var(
Rooms RoomRepository
ShopItems ShopItemRepository
Users UserRepository
)
type RoomRepository interface {
Create(models.Room) (models.Room, error)
GetAll() ([]models.Room, error)
GetById(string) (models.Room, error)
Update(models.Room) (models.Room, error)
DeleteById(string) error
GetRoomUsersById(string) ([]models.User, error)
AddRoomUserById(string, models.User) error
}
type UserRepository interface {
Create(models.User) (models.User, error)
GetByEmail(string) (models.User, error)
GetById(interface{}) (models.User, error)
GetOwnedRooms(models.User) ([]models.Room, error)
}
func InitRepositories() {
db, err := gorm.Open(sqlite.Open(os.Getenv("SQLITE_DB")), &gorm.Config{})
if err != nil {
panic("failed to connect to database")
}
err = db.AutoMigrate(&models.Room{}, &models.User{}, &models.Booking{})
err = db.AutoMigrate(&models.ShopItem{}, &models.User{}, &models.Booking{})
if err != nil {
panic("failed to migrate database")
}
Rooms = NewGORMRoomRepository(db)
ShopItems = NewGORMShopItemRepository(db)
Users = NewGORMUserRepository(db)
}
type GORMUserRepository struct {
DB *gorm.DB
}
type GORMRoomRepository struct {
DB *gorm.DB
}
func NewGORMUserRepository(db *gorm.DB) UserRepository {
return &GORMUserRepository{
DB: db,
}
}
func NewGORMRoomRepository(db *gorm.DB) RoomRepository {
return &GORMRoomRepository{
DB: db,
}
}
func (r *GORMRoomRepository) Create(room models.Room) (models.Room, error) {
result := r.DB.Create(&room)
if result.Error != nil {
return models.Room{}, result.Error
}
return room, nil
}
func (r *GORMRoomRepository) GetAll() ([]models.Room, error){
var rooms []models.Room
result := r.DB.Find(&rooms)
return rooms, result.Error
}
func (r *GORMRoomRepository) GetById(id string) (models.Room, error) {
roomId, err := strconv.Atoi(id)
if err != nil {
return models.Room{}, err
}
var room models.Room
result := r.DB.First(&room, uint(roomId))
if result.Error != nil {
return models.Room{}, result.Error
}
return room, nil
}
func (r *GORMRoomRepository) Update(room models.Room) (models.Room, error) {
result := r.DB.Save(&room)
if result.Error != nil {
return models.Room{}, result.Error
}
return room, nil
}
func (r *GORMRoomRepository) DeleteById(id string) error {
roomId, err := strconv.Atoi(id)
if err != nil {
return err
}
result := r.DB.Delete(&models.Room{}, roomId)
return result.Error
}
func (r *GORMRoomRepository) GetRoomUsersById(id string) ([]models.User, error) {
roomId, err := strconv.Atoi(id)
if err != nil {
return nil, err
}
var room models.Room
result := r.DB.First(&room, uint(roomId))
if result.Error != nil {
return nil, result.Error
}
var users []models.User
err = r.DB.Model(&room).Association("Users").Find(&users)
if err != nil {
return nil, err
}
return users, nil
}
func (r *GORMRoomRepository) AddRoomUserById(id string, user models.User) error {
roomId, err := strconv.Atoi(id)
if err != nil {
return err
}
var room models.Room
result := r.DB.First(&room, uint(roomId))
if result.Error != nil {
return result.Error
}
err = r.DB.Model(&room).Association("Users").Append(&user)
return err
}
func (u *GORMUserRepository) Create(user models.User) (models.User, error) {
result := u.DB.Create(&user)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}
func (u *GORMUserRepository) GetByEmail(email string) (models.User, error) {
var user models.User
result := u.DB.First(&user, "email = ?", email)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}
func (u *GORMUserRepository) GetById(id interface{}) (models.User, error) {
var user models.User
result := u.DB.First(&user, id)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}
func (u *GORMUserRepository) GetOwnedRooms(user models.User) ([]models.Room, error) {
var rooms []models.Room
err := u.DB.Model(&user).Association("OwnedRooms").Find(&rooms)
return rooms, err
}

View File

@@ -0,0 +1,88 @@
package repositories
import(
"strconv"
"gorm.io/gorm"
"example.com/gin/test/models"
)
type ShopItemRepository interface {
Create(models.ShopItem) (models.ShopItem, error)
GetAll() ([]models.ShopItem, error)
GetAllPublic() ([]models.ShopItem, error)
GetById(string) (models.ShopItem, error)
Update(models.ShopItem) (models.ShopItem, error)
DeleteById(string) error
}
type GORMShopItemRepository struct {
DB *gorm.DB
}
func NewGORMShopItemRepository(db *gorm.DB) ShopItemRepository {
return &GORMShopItemRepository{
DB: db,
}
}
func (r *GORMShopItemRepository) Create(shopItem models.ShopItem) (models.ShopItem, error) {
result := r.DB.Create(&shopItem)
if result.Error != nil {
return models.ShopItem{}, result.Error
}
return shopItem, nil
}
func (r *GORMShopItemRepository) GetAll() ([]models.ShopItem, error) {
var shopItems []models.ShopItem
result := r.DB.Find(&shopItems)
return shopItems, result.Error
}
func (r *GORMShopItemRepository) GetAllPublic() ([]models.ShopItem, error) {
var shopItems []models.ShopItem
result := r.DB.Where("is_public = 1").Find(&shopItems)
return shopItems, result.Error
}
func (r *GORMShopItemRepository) GetById(id string) (models.ShopItem, error) {
shopItemId, err := strconv.Atoi(id)
if err != nil {
return models.ShopItem{}, err
}
var shopItem models.ShopItem
result := r.DB.First(&shopItem, uint(shopItemId))
if result.Error != nil {
return models.ShopItem{}, result.Error
}
return shopItem, nil
}
func (r *GORMShopItemRepository) Update(shopItem models.ShopItem) (models.ShopItem, error) {
result := r.DB.Save(&shopItem)
if result.Error != nil {
return models.ShopItem{}, result.Error
}
return shopItem, nil
}
func (r *GORMShopItemRepository) DeleteById(id string) error {
shopItemId, err := strconv.Atoi(id)
if err != nil {
return err
}
result := r.DB.Delete(&models.ShopItem{}, shopItemId)
return result.Error
}

View File

@@ -0,0 +1,55 @@
package repositories
import(
"gorm.io/gorm"
"example.com/gin/test/models"
)
type UserRepository interface {
Create(models.User) (models.User, error)
GetByEmail(string) (models.User, error)
GetById(interface{}) (models.User, error)
}
type GORMUserRepository struct {
DB *gorm.DB
}
func NewGORMUserRepository(db *gorm.DB) UserRepository {
return &GORMUserRepository{
DB: db,
}
}
func (u *GORMUserRepository) Create(user models.User) (models.User, error) {
result := u.DB.Create(&user)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}
func (u *GORMUserRepository) GetByEmail(email string) (models.User, error) {
var user models.User
result := u.DB.First(&user, "email = ?", email)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}
func (u *GORMUserRepository) GetById(id interface{}) (models.User, error) {
var user models.User
result := u.DB.First(&user, id)
if result.Error != nil {
return models.User{}, result.Error
}
return user, nil
}