mirror of
https://github.com/pushbits/server.git
synced 2025-04-30 10:46:55 +02:00
Some plugins check for token length. Since PushBits uses longer tokens by default for better security, these plugins are incompatible. With this patch, users can decide if they want an application to have a short token, so that said plugins can talk to PushBits again.
213 lines
5.5 KiB
Go
213 lines
5.5 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/pushbits/server/internal/authentication"
|
|
"github.com/pushbits/server/internal/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// ApplicationHandler holds information for processing requests about applications.
|
|
type ApplicationHandler struct {
|
|
DB Database
|
|
DP Dispatcher
|
|
}
|
|
|
|
func (h *ApplicationHandler) applicationExists(token string) bool {
|
|
application, _ := h.DB.GetApplicationByToken(token)
|
|
return application != nil
|
|
}
|
|
|
|
func (h *ApplicationHandler) generateToken(compat bool) string {
|
|
return authentication.GenerateNotExistingToken(authentication.GenerateApplicationToken, compat, h.applicationExists)
|
|
}
|
|
|
|
func (h *ApplicationHandler) registerApplication(ctx *gin.Context, a *model.Application, u *model.User) error {
|
|
log.Printf("Registering application %s.\n", a.Name)
|
|
|
|
channelID, err := h.DP.RegisterApplication(a.ID, a.Name, a.Token, u.MatrixID)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return err
|
|
}
|
|
|
|
a.MatrixID = channelID
|
|
h.DB.UpdateApplication(a)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *ApplicationHandler) createApplication(ctx *gin.Context, u *model.User, name string, compat bool) (*model.Application, error) {
|
|
log.Printf("Creating application %s.\n", name)
|
|
|
|
application := model.Application{}
|
|
application.Name = name
|
|
application.Token = h.generateToken(compat)
|
|
application.UserID = u.ID
|
|
|
|
err := h.DB.CreateApplication(&application)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return nil, err
|
|
}
|
|
|
|
if err := h.registerApplication(ctx, &application, u); err != nil {
|
|
err := h.DB.DeleteApplication(&application)
|
|
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
log.Printf("Cannot delete application with ID %d.\n", application.ID)
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
return &application, nil
|
|
}
|
|
|
|
func (h *ApplicationHandler) deleteApplication(ctx *gin.Context, a *model.Application, u *model.User) error {
|
|
log.Printf("Deleting application %s (ID %d).\n", a.Name, a.ID)
|
|
|
|
err := h.DP.DeregisterApplication(a, u)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return err
|
|
}
|
|
|
|
err = h.DB.DeleteApplication(a)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *ApplicationHandler) updateApplication(ctx *gin.Context, a *model.Application, u *model.User, updateApplication *model.UpdateApplication) error {
|
|
log.Printf("Updating application %s (ID %d).\n", a.Name, a.ID)
|
|
|
|
if updateApplication.Name != nil {
|
|
log.Printf("Updating application name to '%s'.", *updateApplication.Name)
|
|
a.Name = *updateApplication.Name
|
|
}
|
|
|
|
if updateApplication.RefreshToken != nil && (*updateApplication.RefreshToken) {
|
|
log.Print("Updating application token.")
|
|
compat := updateApplication.StrictCompatibility != nil && (*updateApplication.StrictCompatibility)
|
|
a.Token = h.generateToken(compat)
|
|
}
|
|
|
|
err := h.DB.UpdateApplication(a)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return err
|
|
}
|
|
|
|
err = h.DP.UpdateApplication(a, u)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CreateApplication creates an application.
|
|
func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) {
|
|
var createApplication model.CreateApplication
|
|
|
|
if err := ctx.Bind(&createApplication); err != nil {
|
|
return
|
|
}
|
|
|
|
user := authentication.GetUser(ctx)
|
|
if user == nil {
|
|
return
|
|
}
|
|
|
|
application, err := h.createApplication(ctx, user, createApplication.Name, createApplication.StrictCompatibility)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, &application)
|
|
}
|
|
|
|
// GetApplications returns all applications of the current user.
|
|
func (h *ApplicationHandler) GetApplications(ctx *gin.Context) {
|
|
user := authentication.GetUser(ctx)
|
|
if user == nil {
|
|
return
|
|
}
|
|
|
|
applications, err := h.DB.GetApplications(user)
|
|
if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success {
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, &applications)
|
|
}
|
|
|
|
// GetApplication returns the application with the specified ID.
|
|
func (h *ApplicationHandler) GetApplication(ctx *gin.Context) {
|
|
application, err := getApplication(ctx, h.DB)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
user := authentication.GetUser(ctx)
|
|
if user == 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 := getApplication(ctx, h.DB)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if !isCurrentUser(ctx, application.UserID) {
|
|
return
|
|
}
|
|
|
|
if err := h.deleteApplication(ctx, application, authentication.GetUser(ctx)); err != nil {
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, gin.H{})
|
|
}
|
|
|
|
// UpdateApplication updates an application with a certain ID.
|
|
func (h *ApplicationHandler) UpdateApplication(ctx *gin.Context) {
|
|
application, err := getApplication(ctx, h.DB)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if !isCurrentUser(ctx, application.UserID) {
|
|
return
|
|
}
|
|
|
|
var updateApplication model.UpdateApplication
|
|
if err := ctx.Bind(&updateApplication); err != nil {
|
|
return
|
|
}
|
|
|
|
user := authentication.GetUser(ctx)
|
|
if user == nil {
|
|
return
|
|
}
|
|
|
|
if err := h.updateApplication(ctx, application, user, &updateApplication); err != nil {
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, gin.H{})
|
|
}
|