pushbits/api/user.go
2020-07-31 19:58:06 +02:00

102 lines
2.6 KiB
Go

package api
import (
"errors"
"log"
"net/http"
"github.com/eikendev/pushbits/model"
"github.com/gin-gonic/gin"
)
// The UserDatabase interface for encapsulating database access.
type UserDatabase interface {
CreateUser(user model.ExternalUserWithCredentials) (*model.User, error)
DeleteUser(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)
}
// The UserDispatcher interface for relaying notifications.
type UserDispatcher interface {
DeregisterApplication(a *model.Application) error
}
// UserHandler holds information for processing requests about users.
type UserHandler struct {
DB UserDatabase
Dispatcher ApplicationDispatcher
}
func (h *UserHandler) userExists(name string) bool {
user, _ := h.DB.GetUserByName(name)
return user != nil
}
// CreateUser creates a new user.
func (h *UserHandler) CreateUser(ctx *gin.Context) {
var externalUser model.ExternalUserWithCredentials
if success := successOrAbort(ctx, http.StatusBadRequest, ctx.Bind(&externalUser)); !success {
return
}
if h.userExists(externalUser.Name) {
ctx.AbortWithError(http.StatusBadRequest, errors.New("username already exists"))
return
}
user, err := h.DB.CreateUser(externalUser)
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
return
}
ctx.JSON(http.StatusOK, user.IntoExternalUser())
}
// DeleteUser deletes a user with a certain ID.
func (h *UserHandler) DeleteUser(ctx *gin.Context) {
var deleteUser model.DeleteUser
if success := successOrAbort(ctx, http.StatusBadRequest, ctx.BindUri(&deleteUser)); !success {
return
}
user, err := h.DB.GetUserByID(deleteUser.ID)
if success := successOrAbort(ctx, http.StatusBadRequest, err); !success {
return
}
if user.IsAdmin {
if count, err := h.DB.AdminUserCount(); err != nil {
ctx.AbortWithError(http.StatusInternalServerError, err)
return
} else if count == 1 {
ctx.AbortWithError(http.StatusBadRequest, errors.New("cannot delete last admin user"))
return
}
}
log.Printf("Deleting user %s.\n", user.Name)
applications, err := h.DB.GetApplications(user)
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
return
}
for _, app := range applications {
if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.DeregisterApplication(&app)); !success {
return
}
}
if success := successOrAbort(ctx, http.StatusInternalServerError, h.DB.DeleteUser(user)); !success {
return
}
ctx.JSON(http.StatusOK, gin.H{})
}