diff --git a/api/application.go b/api/application.go index 0b92014..98037bd 100644 --- a/api/application.go +++ b/api/application.go @@ -13,12 +13,15 @@ import ( // The ApplicationDatabase interface for encapsulating database access. type ApplicationDatabase interface { CreateApplication(application *model.Application) error + DeleteApplication(application *model.Application) error + GetApplicationByID(ID uint) (*model.Application, error) GetApplicationByToken(token string) (*model.Application, error) } // The ApplicationDispatcher interface for relaying notifications. type ApplicationDispatcher interface { RegisterApplication(name, user string) (string, error) + DeregisterApplication(matrixID string) error } // ApplicationHandler holds information for processing requests about applications. @@ -32,16 +35,17 @@ func (h *ApplicationHandler) applicationExists(token string) bool { return application != nil } -// CreateApplication is used to create a new user. +// CreateApplication creates a user. func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) { - application := model.Application{} + var createApplication model.CreateApplication - if success := successOrAbort(ctx, http.StatusBadRequest, ctx.Bind(&application)); !success { + if success := successOrAbort(ctx, http.StatusBadRequest, ctx.Bind(&createApplication)); !success { return } user := authentication.GetUser(ctx) + application := model.Application{} application.Token = authentication.GenerateNotExistingToken(authentication.GenerateApplicationToken, h.applicationExists) application.UserID = user.ID @@ -61,3 +65,30 @@ func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) { ctx.JSON(http.StatusOK, &application) } + +// DeleteApplication deletes a user with a certain ID. +func (h *ApplicationHandler) DeleteApplication(ctx *gin.Context) { + var deleteApplication model.DeleteApplication + + if success := successOrAbort(ctx, http.StatusBadRequest, ctx.BindUri(&deleteApplication)); !success { + return + } + + 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 { + return + } + + if success := successOrAbort(ctx, http.StatusInternalServerError, h.DB.DeleteApplication(application)); !success { + return + } + + ctx.JSON(http.StatusOK, gin.H{}) +} diff --git a/api/notification.go b/api/notification.go index 067d180..859ef17 100644 --- a/api/notification.go +++ b/api/notification.go @@ -29,7 +29,7 @@ type NotificationHandler struct { // CreateNotification is used to create a new notification for a user. func (h *NotificationHandler) CreateNotification(ctx *gin.Context) { - notification := model.Notification{} + var notification model.Notification if success := successOrAbort(ctx, http.StatusBadRequest, ctx.Bind(¬ification)); !success { return diff --git a/api/user.go b/api/user.go index a161fbe..4793eb5 100644 --- a/api/user.go +++ b/api/user.go @@ -27,7 +27,7 @@ func (h *UserHandler) userExists(name string) bool { // CreateUser creates a new user. func (h *UserHandler) CreateUser(ctx *gin.Context) { - externalUser := model.ExternalUserWithCredentials{} + var externalUser model.ExternalUserWithCredentials if success := successOrAbort(ctx, http.StatusBadRequest, ctx.Bind(&externalUser)); !success { return diff --git a/database/application.go b/database/application.go index bef3d13..66b4065 100644 --- a/database/application.go +++ b/database/application.go @@ -13,11 +13,28 @@ func (d *Database) CreateApplication(application *model.Application) error { return d.gormdb.Create(application).Error } +// DeleteApplication deletes an application. +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. +func (d *Database) GetApplicationByID(ID uint) (*model.Application, error) { + app := new(model.Application) + err := d.gormdb.First(&app, ID).Error + + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + + return app, err +} + // GetApplicationByToken returns the application for the given token or nil. func (d *Database) GetApplicationByToken(token string) (*model.Application, error) { app := new(model.Application) diff --git a/dispatcher/application.go b/dispatcher/application.go index b4ab7f7..f8c1c14 100644 --- a/dispatcher/application.go +++ b/dispatcher/application.go @@ -6,7 +6,7 @@ import ( "github.com/matrix-org/gomatrix" ) -// RegisterApplication creates a new channel for the application. +// RegisterApplication creates a new channel for an application. func (d *Dispatcher) RegisterApplication(name, user string) (string, error) { log.Printf("Registering application %s, notifications will be relayed to user %s.\n", name, user) @@ -27,3 +27,16 @@ func (d *Dispatcher) RegisterApplication(name, user string) (string, error) { return response.RoomID, err } + +// DeregisterApplication deletes a channel for an application. +func (d *Dispatcher) DeregisterApplication(matrixID string) error { + log.Printf("Deregistering application with ID %s.\n", matrixID) + + _, err := d.client.LeaveRoom(matrixID) + + if err != nil { + log.Fatal(err) + } + + return err +} diff --git a/model/application.go b/model/application.go index 01e1e6c..d292674 100644 --- a/model/application.go +++ b/model/application.go @@ -5,6 +5,16 @@ type Application struct { ID uint `gorm:"AUTO_INCREMENT;primary_key" json:"id"` Token string `gorm:"type:string;size:64;unique" json:"token"` UserID uint `json:"-"` - Name string `gorm:"type:string" form:"name" query:"name" json:"name" binding:"required"` - MatrixID string `gorm:"type:string"` + Name string `gorm:"type:string" json:"name"` + MatrixID string `gorm:"type:string" json:"-"` +} + +// CreateApplication is used to process queries for creating applications. +type CreateApplication struct { + Name string `form:"name" query:"name" json:"name" binding:"required"` +} + +// DeleteApplication is used to process queries for deleting applications. +type DeleteApplication struct { + ID uint `uri:"id"` } diff --git a/router/router.go b/router/router.go index 41ea3af..2977ead 100644 --- a/router/router.go +++ b/router/router.go @@ -29,7 +29,7 @@ func Create(db *database.Database, dp *dispatcher.Dispatcher) *gin.Engine { applicationGroup.Use(auth.RequireUser()) { applicationGroup.POST("", applicationHandler.CreateApplication) - //applicationGroup.DELETE("/:id", applicationHandler.DeleteApplication) + applicationGroup.DELETE("/:id", applicationHandler.DeleteApplication) } r.POST("/message", auth.RequireApplicationToken(), notificationHandler.CreateNotification)