diff --git a/controllers/roomController.go b/controllers/roomController.go index c5d0dcc..fc55c36 100644 --- a/controllers/roomController.go +++ b/controllers/roomController.go @@ -6,9 +6,9 @@ import ( "strconv" "github.com/gin-gonic/gin" - "gorm.io/gorm" "example.com/gin/test/models" + "example.com/gin/test/repositories" ) type CRUDController interface { @@ -25,21 +25,16 @@ type RoomController interface { AddUser(*gin.Context) } -type roomController struct { - DB *gorm.DB -} +type roomController struct {} -func NewRoomController(db *gorm.DB) RoomController { - return &roomController{ - DB: db, - } +func NewRoomController() RoomController { + return &roomController{} } func (rc *roomController) GetAll(c *gin.Context) { - var rooms []models.Room - result := rc.DB.Find(&rooms) + rooms, err := repositories.Rooms.GetAll() - if result.Error != nil { + if err != nil { ReplyError(c, fmt.Errorf("Could not query rooms")) return } @@ -48,18 +43,10 @@ func (rc *roomController) GetAll(c *gin.Context) { } func (rc *roomController) GetById(c *gin.Context) { - roomId, err := strconv.Atoi(c.Param("id")) + room, err := repositories.Rooms.GetById(c.Param("id")) if err != nil { - ReplyError(c, fmt.Errorf("Room with Id '%s' does not exist", c.Param("id"))) - return - } - - var room models.Room - result := rc.DB.First(&room, uint(roomId)) - - if result.Error != nil { - ReplyError(c, fmt.Errorf("Could not query room: %v", result.Error)) + ReplyError(c, fmt.Errorf("Could not query room: %v", err)) return } @@ -80,9 +67,9 @@ func (rc *roomController) Create(c *gin.Context) { ReplyError(c, err) } - result := rc.DB.Create(&room) - if result.Error != nil { - ReplyError(c, fmt.Errorf("Room creation failed: %s", result.Error)) + _, err = repositories.Rooms.Create(room) + if err != nil { + ReplyError(c, fmt.Errorf("Room creation failed: %s", err)) return } @@ -114,9 +101,10 @@ func (rc *roomController) Update(c *gin.Context) { } room.ID = uint(roomId) - result := rc.DB.Save(&room) - if result.Error != nil { - ReplyError(c, fmt.Errorf("Room creation failed: %s", result.Error)) + _, err = repositories.Rooms.Update(room) + + if err != nil { + ReplyError(c, fmt.Errorf("Room creation failed: %s", err)) return } @@ -124,17 +112,10 @@ func (rc *roomController) Update(c *gin.Context) { } func (rc *roomController) Delete(c *gin.Context) { - roomId, err := strconv.Atoi(c.Param("id")) + err := repositories.Rooms.DeleteById(c.Param("id")) if err != nil { - ReplyError(c, fmt.Errorf("Room with Id '%s' does not exist", c.Param("id"))) - return - } - - result := rc.DB.Delete(&models.Room{}, roomId) - - if result.Error != nil { - ReplyError(c, fmt.Errorf("Room deletion failed: %s", result.Error)) + ReplyError(c, fmt.Errorf("Room deletion failed: %s", err)) return } @@ -144,23 +125,12 @@ func (rc *roomController) Delete(c *gin.Context) { func (rc *roomController) GetUsers(c *gin.Context) { //only allow room admin - roomId, err := strconv.Atoi(c.Param("id")) + users, err := repositories.Rooms.GetRoomUsersById(c.Param("id")) if err != nil { - ReplyError(c, fmt.Errorf("Room with Id '%s' does not exist", c.Param("id"))) + ReplyError(c, fmt.Errorf("Could not get users for room '%s'", c.Param("id"))) return } - - var room models.Room - result := rc.DB.First(&room, uint(roomId)) - - if result.Error != nil { - ReplyError(c, fmt.Errorf("Could not query room: %v", result.Error)) - return - } - - var users []models.User - rc.DB.Model(&room).Association("Users").Find(&users) var emails []string for _, user := range users { @@ -188,10 +158,9 @@ func (rc *roomController) AddUser(c *gin.Context) { } //lookup requested user - var user models.User - result := rc.DB.First(&user, "email = ?", body.Email) + user, err := repositories.Users.GetByEmail(body.Email) - if result.Error != nil { + if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid user", }) @@ -199,22 +168,13 @@ func (rc *roomController) AddUser(c *gin.Context) { return } - roomId, err := strconv.Atoi(c.Param("id")) + err = repositories.Rooms.AddRoomUserById(c.Param("id"), user) if err != nil { - ReplyError(c, fmt.Errorf("Room with Id '%s' does not exist", c.Param("id"))) + ReplyError(c, fmt.Errorf("Could not add user to room.")) return } - var room models.Room - result = rc.DB.First(&room, uint(roomId)) - - if result.Error != nil { - ReplyError(c, fmt.Errorf("Could not query room: %v", result.Error)) - return - } - - rc.DB.Model(&room).Association("Users").Append(&user) ReplyOK(c, "Added User to Room") } diff --git a/controllers/userController.go b/controllers/userController.go index 66e2a46..24947da 100644 --- a/controllers/userController.go +++ b/controllers/userController.go @@ -9,20 +9,16 @@ import( "github.com/golang-jwt/jwt/v5" "github.com/gin-gonic/gin" - "gorm.io/gorm" "example.com/gin/test/models" + "example.com/gin/test/repositories" ) -type UserController struct { - DB *gorm.DB -} +type UserController struct {} -func NewUserController(db *gorm.DB) UserController { - return UserController{ - DB: db, - } +func NewUserController() UserController { + return UserController{} } @@ -57,10 +53,10 @@ func (uc *UserController) Register(c *gin.Context) { //create user user := models.User{Name: body.Name, Email: body.Email, Password: string(hash)} - result := uc.DB.Create(&user) + _, err = repositories.Users.Create(user) - if result.Error != nil { - fmt.Println("Error: ", result.Error) + if err != nil { + fmt.Println("Error: ", err) c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to create user", }) @@ -92,10 +88,9 @@ func (uc *UserController) Login(c *gin.Context) { } //lookup requested user - var user models.User - result := uc.DB.First(&user, "email = ?", body.Email) + user, err := repositories.Users.GetByEmail(body.Email) - if result.Error != nil { + if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid email or password", }) @@ -151,3 +146,48 @@ func (uc *UserController) Validate(c *gin.Context) { }) } } + +func (rc *UserController) LoginView(c *gin.Context) { + rooms, _ := repositories.Rooms.GetAll() + + data := gin.H{ + "title": "Room Page", + "rooms": rooms, + } + + c.HTML(http.StatusOK, "login.html", data) +} + +func (rc *UserController) RegisterView(c *gin.Context) { + rooms, _ := repositories.Rooms.GetAll() + + data := gin.H{ + "title": "Room Page", + "rooms": rooms, + } + + c.HTML(http.StatusOK, "register.html", data) +} + +func (rc *UserController) ResetView(c *gin.Context) { + rooms, _ := repositories.Rooms.GetAll() + + data := gin.H{ + "title": "Room Page", + "rooms": rooms, + } + + c.HTML(http.StatusOK, "passwordreset.html", data) +} + +func (rc *UserController) MainView(c *gin.Context) { + rooms, _ := repositories.Rooms.GetAll() + + data := gin.H{ + "title": "Room Page", + "rooms": rooms, + } + + c.HTML(http.StatusOK, "index.html", data) +} + diff --git a/main.go b/main.go index 4d16222..751b117 100644 --- a/main.go +++ b/main.go @@ -6,20 +6,18 @@ import( "net/http" "fmt" - "gorm.io/gorm" - "gorm.io/driver/sqlite" "github.com/gin-gonic/gin" "github.com/joho/godotenv" "example.com/gin/test/controllers" - "example.com/gin/test/models" + "example.com/gin/test/repositories" "example.com/gin/test/middlewares" ) var( - roomController controllers.RoomController - userController controllers.UserController - autoValidator middlewares.AuthValidator + roomController controllers.RoomController = controllers.NewRoomController() + userController controllers.UserController = controllers.UserController{} + authValidator middlewares.AuthValidator = middlewares.AuthValidator{} ) func LoadEnvVariables() { @@ -46,19 +44,8 @@ func SetReply(ctx *gin.Context, err error, message any) { func main() { LoadEnvVariables() - db, err := gorm.Open(sqlite.Open(os.Getenv("SQLITE_DB")), &gorm.Config{}) - if err != nil { - panic("failed to connect to database") - } + repositories.InitRepositories() - err = db.AutoMigrate(&models.Room{}, &models.User{}, &models.Booking{}) - if err != nil { - panic("failed to migrate database") - } - - roomController = controllers.NewRoomController(db) - userController = controllers.NewUserController(db) - authValidator := middlewares.AuthValidator{ DB: db, } server := gin.New() server.Use(gin.Recovery()) @@ -84,5 +71,14 @@ func main() { apiRoutes.GET("/users/validate", authValidator.OptionalAuth, userController.Validate) } + viewRoutes := server.Group("/") + { + viewRoutes.GET("/", userController.MainView) + viewRoutes.GET("/login", userController.LoginView) + viewRoutes.GET("/register", userController.RegisterView) + viewRoutes.GET("/passwordreset", userController.ResetView) + } + + server.Run(":"+os.Getenv("PORT")) } diff --git a/middlewares/requireAuth.go b/middlewares/requireAuth.go index 02899b2..8251a03 100644 --- a/middlewares/requireAuth.go +++ b/middlewares/requireAuth.go @@ -8,13 +8,12 @@ import( "net/http" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" - "gorm.io/gorm" "example.com/gin/test/models" + "example.com/gin/test/repositories" ) type AuthValidator struct { - DB *gorm.DB } func (av *AuthValidator) RequireRoomAdmin(c *gin.Context) { @@ -30,8 +29,12 @@ func (av *AuthValidator) RequireRoomAdmin(c *gin.Context) { return } - var rooms []models.Room - av.DB.Model(&user).Association("OwnedRooms").Find(&rooms) + 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) { @@ -77,10 +80,9 @@ func (av *AuthValidator) RequireAuth(c *gin.Context) { } //Find user - var user models.User - result := av.DB.First(&user, claims["sub"]) + user, err := repositories.Users.GetById(claims["sub"]) - if result.Error != nil { + if err != nil { c.AbortWithStatus(http.StatusUnauthorized) return } @@ -124,10 +126,9 @@ func (av *AuthValidator) OptionalAuth(c *gin.Context) { } //Find user - var user models.User - result := av.DB.First(&user, claims["sub"]) + user, err := repositories.Users.GetById(claims["sub"]) - if result.Error != nil { + if err != nil { return } diff --git a/repositories/repository.go b/repositories/repository.go new file mode 100644 index 0000000..c90f317 --- /dev/null +++ b/repositories/repository.go @@ -0,0 +1,201 @@ +package repositories + +import( + "os" + "strconv" + "gorm.io/gorm" + "gorm.io/driver/sqlite" + + "example.com/gin/test/models" +) + +var( + Rooms RoomRepository + 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{}) + if err != nil { + panic("failed to migrate database") + } + + Rooms = NewGORMRoomRepository(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 +}