Implement deletion of users

This commit is contained in:
eikendev 2020-07-27 00:53:32 +02:00
parent 18d11677ac
commit f6ca287d0b
No known key found for this signature in database
GPG key ID: A1BDB1B28C8EF694
10 changed files with 112 additions and 35 deletions

View file

@ -21,7 +21,7 @@ type ApplicationDatabase interface {
// The ApplicationDispatcher interface for relaying notifications.
type ApplicationDispatcher interface {
RegisterApplication(name, user string) (string, error)
DeregisterApplication(matrixID string) error
DeregisterApplication(a *model.Application) error
}
// ApplicationHandler holds information for processing requests about applications.
@ -35,7 +35,7 @@ func (h *ApplicationHandler) applicationExists(token string) bool {
return application != nil
}
// CreateApplication creates a user.
// CreateApplication creates an application.
func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) {
var createApplication model.CreateApplication
@ -66,7 +66,7 @@ func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) {
ctx.JSON(http.StatusOK, &application)
}
// DeleteApplication deletes a user with a certain ID.
// DeleteApplication deletes an application with a certain ID.
func (h *ApplicationHandler) DeleteApplication(ctx *gin.Context) {
var deleteApplication model.DeleteApplication
@ -76,13 +76,13 @@ func (h *ApplicationHandler) DeleteApplication(ctx *gin.Context) {
application, err := h.DB.GetApplicationByID(deleteApplication.ID)
log.Printf("Deleting application %s.\n", application.Name)
if success := successOrAbort(ctx, http.StatusBadRequest, err); !success {
return
}
if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.DeregisterApplication(application.MatrixID)); !success {
log.Printf("Deleting application %s.\n", application.Name)
if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.DeregisterApplication(application)); !success {
return
}

View file

@ -2,6 +2,7 @@ package api
import (
"errors"
"log"
"net/http"
"github.com/eikendev/pushbits/model"
@ -12,12 +13,21 @@ import (
// The UserDatabase interface for encapsulating database access.
type UserDatabase interface {
CreateUser(user *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)
}
// 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
DB UserDatabase
Dispatcher ApplicationDispatcher
}
func (h *UserHandler) userExists(name string) bool {
@ -46,3 +56,36 @@ func (h *UserHandler) CreateUser(ctx *gin.Context) {
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
}
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{})
}

View file

@ -28,7 +28,7 @@ func configFiles() []string {
// Get returns the configuration extracted from env variables or config file.
func Get() *Configuration {
config := new(Configuration)
config := &Configuration{}
err := configor.New(&configor.Config{
Environment: "production",

View file

@ -18,31 +18,28 @@ func (d *Database) DeleteApplication(application *model.Application) error {
return d.gormdb.Delete(application).Error
}
// UpdateApplication updates an application.
func (d *Database) UpdateApplication(app *model.Application) error {
return d.gormdb.Save(app).Error
}
// GetApplicationByID returns the application for the given ID or nil.
// GetApplicationByID returns the application with the given ID or nil.
func (d *Database) GetApplicationByID(ID uint) (*model.Application, error) {
app := new(model.Application)
var app model.Application
err := d.gormdb.First(&app, ID).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
return app, err
return &app, err
}
// GetApplicationByToken returns the application for the given token or nil.
// GetApplicationByToken returns the application with the given token or nil.
func (d *Database) GetApplicationByToken(token string) (*model.Application, error) {
app := new(model.Application)
err := d.gormdb.Where("token = ?", token).First(app).Error
var app model.Application
err := d.gormdb.Where("token = ?", token).First(&app).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
return app, err
return &app, err
}

View file

@ -78,8 +78,9 @@ func (d *Database) Close() {
// Populate fills the database with initial information like the admin user.
func (d *Database) Populate(name, password, matrixID string) error {
user := new(model.User)
query := d.gormdb.Where("name = ?", name).First(user)
var user model.User
query := d.gormdb.Where("name = ?", name).First(&user)
if errors.Is(query.Error, gorm.ErrRecordNotFound) {
user := model.NewUser(name, password, true, matrixID)

View file

@ -13,14 +13,46 @@ func (d *Database) CreateUser(user *model.User) error {
return d.gormdb.Create(user).Error
}
// GetUserByName returns the user by the given name or nil.
func (d *Database) GetUserByName(name string) (*model.User, error) {
user := new(model.User)
err := d.gormdb.Where("name = ?", name).First(user).Error
// DeleteUser deletes a user.
func (d *Database) DeleteUser(user *model.User) error {
if err := d.gormdb.Where("user_id = ?", user.ID).Delete(model.Application{}).Error; err != nil {
return err
}
return d.gormdb.Delete(user).Error
}
// GetUserByID returns the user with the given ID or nil.
func (d *Database) GetUserByID(ID uint) (*model.User, error) {
var user model.User
err := d.gormdb.First(&user, ID).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
return user, err
return &user, err
}
// GetUserByName returns the user with the given name or nil.
func (d *Database) GetUserByName(name string) (*model.User, error) {
var user model.User
err := d.gormdb.Where("name = ?", name).First(&user).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
return &user, err
}
// GetApplications returns the applications associated with a given user.
func (d *Database) GetApplications(user *model.User) ([]model.Application, error) {
var applications []model.Application
err := d.gormdb.Model(user).Association("Applications").Find(&applications)
return applications, err
}

View file

@ -3,6 +3,8 @@ package dispatcher
import (
"log"
"github.com/eikendev/pushbits/model"
"github.com/matrix-org/gomatrix"
)
@ -29,10 +31,10 @@ func (d *Dispatcher) RegisterApplication(name, user string) (string, error) {
}
// DeregisterApplication deletes a channel for an application.
func (d *Dispatcher) DeregisterApplication(matrixID string) error {
log.Printf("Deregistering application with ID %s.\n", matrixID)
func (d *Dispatcher) DeregisterApplication(a *model.Application) error {
log.Printf("Deregistering application with ID %s.\n", a.MatrixID)
_, err := d.client.LeaveRoom(matrixID)
_, err := d.client.LeaveRoom(a.MatrixID)
if err != nil {
log.Fatal(err)

View file

@ -3,8 +3,6 @@ package dispatcher
import (
"log"
"github.com/eikendev/pushbits/model"
"github.com/matrix-org/gomatrix"
)
@ -14,7 +12,6 @@ var (
// The Database interface for encapsulating database access.
type Database interface {
UpdateApplication(application *model.Application) error
}
// Dispatcher holds information for sending notifications to clients.

View file

@ -68,3 +68,8 @@ func (u *User) IntoExternalUser() *ExternalUser {
MatrixID: u.MatrixID,
}
}
// DeleteUser is used to process queries for deleting users.
type DeleteUser struct {
ID uint `uri:"id"`
}

View file

@ -20,7 +20,7 @@ func Create(db *database.Database, dp *dispatcher.Dispatcher) *gin.Engine {
applicationHandler := api.ApplicationHandler{DB: db, Dispatcher: dp}
notificationHandler := api.NotificationHandler{DB: db, Dispatcher: dp}
userHandler := api.UserHandler{DB: db}
userHandler := api.UserHandler{DB: db, Dispatcher: dp}
r := gin.Default()
r.Use(location.Default())
@ -38,7 +38,7 @@ func Create(db *database.Database, dp *dispatcher.Dispatcher) *gin.Engine {
userGroup.Use(auth.RequireAdmin())
{
userGroup.POST("", userHandler.CreateUser)
//userGroup.DELETE("/:id", userHandler.DeleteUser)
userGroup.DELETE("/:id", userHandler.DeleteUser)
}
return r