From a3de04b2a59200aba5736b1f3cac88779a267047 Mon Sep 17 00:00:00 2001 From: eikendev Date: Mon, 3 Aug 2020 23:27:17 +0200 Subject: [PATCH] Implement retrieving of application data --- api/application.go | 42 +++++++++++++++++++++++++++++++++++++++++- api/context.go | 20 ++++++++++++++++++++ api/user.go | 25 ++++++------------------- router/router.go | 3 +++ 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/api/application.go b/api/application.go index 43313da..2c344e8 100644 --- a/api/application.go +++ b/api/application.go @@ -1,6 +1,7 @@ package api import ( + "errors" "log" "net/http" @@ -14,9 +15,12 @@ import ( type ApplicationDatabase interface { CreateApplication(application *model.Application) error DeleteApplication(application *model.Application) error - UpdateApplication(application *model.Application) error GetApplicationByID(ID uint) (*model.Application, error) GetApplicationByToken(token string) (*model.Application, error) + GetApplications(user *model.User) ([]model.Application, error) + UpdateApplication(application *model.Application) error + + GetUserByID(ID uint) (*model.User, error) } // The ApplicationDispatcher interface for relaying notifications. @@ -128,6 +132,42 @@ func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) { ctx.JSON(http.StatusOK, &application) } +// GetApplications returns all applications for the current user. +func (h *ApplicationHandler) GetApplications(ctx *gin.Context) { + user, err := getUser(ctx, h.DB) + if err != nil { + return + } + + applications, err := h.DB.GetApplications(user) + if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success { + return + } + + ctx.JSON(http.StatusOK, &applications) +} + +// GetApplication returns all applications for the current user. +func (h *ApplicationHandler) GetApplication(ctx *gin.Context) { + application, err := h.getApplication(ctx) + if err != nil { + return + } + + user, err := getUser(ctx, h.DB) + if err != nil { + return + } + + if user.ID != application.UserID { + err := errors.New("application belongs to another user") + ctx.AbortWithError(http.StatusForbidden, err) + return + } + + ctx.JSON(http.StatusOK, &application) +} + // DeleteApplication deletes an application with a certain ID. func (h *ApplicationHandler) DeleteApplication(ctx *gin.Context) { application, err := h.getApplication(ctx) diff --git a/api/context.go b/api/context.go index bffd856..989332e 100644 --- a/api/context.go +++ b/api/context.go @@ -4,9 +4,15 @@ import ( "errors" "net/http" + "github.com/eikendev/pushbits/model" + "github.com/gin-gonic/gin" ) +type database interface { + GetUserByID(ID uint) (*model.User, error) +} + func getID(ctx *gin.Context) (uint, error) { id, ok := ctx.MustGet("id").(uint) if !ok { @@ -17,3 +23,17 @@ func getID(ctx *gin.Context) (uint, error) { return id, nil } + +func getUser(ctx *gin.Context, db database) (*model.User, error) { + id, err := getID(ctx) + if err != nil { + return nil, err + } + + application, err := db.GetUserByID(id) + if success := successOrAbort(ctx, http.StatusNotFound, err); !success { + return nil, err + } + + return application, nil +} diff --git a/api/user.go b/api/user.go index 248d7a5..aa26d7e 100644 --- a/api/user.go +++ b/api/user.go @@ -13,13 +13,14 @@ import ( // The UserDatabase interface for encapsulating database access. type UserDatabase interface { + GetApplications(user *model.User) ([]model.Application, error) + + AdminUserCount() (int64, error) CreateUser(user model.CreateUser) (*model.User, error) DeleteUser(user *model.User) error - UpdateUser(user *model.User) error GetUserByID(ID uint) (*model.User, error) GetUserByName(name string) (*model.User, error) - GetApplications(user *model.User) ([]model.Application, error) - AdminUserCount() (int64, error) + UpdateUser(user *model.User) error } // The UserDispatcher interface for relaying notifications. @@ -58,20 +59,6 @@ func (h *UserHandler) requireMultipleAdmins(ctx *gin.Context) error { return nil } -func (h *UserHandler) getUser(ctx *gin.Context) (*model.User, error) { - id, err := getID(ctx) - if err != nil { - return nil, err - } - - application, err := h.DB.GetUserByID(id) - if success := successOrAbort(ctx, http.StatusNotFound, err); !success { - return nil, err - } - - return application, nil -} - func (h *UserHandler) deleteApplications(ctx *gin.Context, u *model.User) error { applications, err := h.DB.GetApplications(u) if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success { @@ -169,7 +156,7 @@ func (h *UserHandler) CreateUser(ctx *gin.Context) { // // This method assumes that the requesting user has privileges. func (h *UserHandler) DeleteUser(ctx *gin.Context) { - user, err := h.getUser(ctx) + user, err := getUser(ctx, h.DB) if err != nil { return } @@ -199,7 +186,7 @@ func (h *UserHandler) DeleteUser(ctx *gin.Context) { // This method assumes that the requesting user has privileges. If users can later update their own user, make sure they // cannot give themselves privileges. func (h *UserHandler) UpdateUser(ctx *gin.Context) { - user, err := h.getUser(ctx) + user, err := getUser(ctx, h.DB) if err != nil { return } diff --git a/router/router.go b/router/router.go index 63d2ef4..fca4479 100644 --- a/router/router.go +++ b/router/router.go @@ -35,6 +35,9 @@ func Create(debug bool, cm *credentials.Manager, db *database.Database, dp *disp applicationGroup.Use(auth.RequireUser()) { applicationGroup.POST("", applicationHandler.CreateApplication) + applicationGroup.GET("", applicationHandler.GetApplications) + + applicationGroup.GET("/:id", api.RequireIDInURI(), applicationHandler.GetApplication) applicationGroup.DELETE("/:id", api.RequireIDInURI(), applicationHandler.DeleteApplication) applicationGroup.PUT("/:id", api.RequireIDInURI(), applicationHandler.UpdateApplication) }