From e1cd2d2f8e047e57b5df79c2b4c5c4da426c9b02 Mon Sep 17 00:00:00 2001 From: eikendev Date: Sun, 2 Aug 2020 14:45:24 +0200 Subject: [PATCH] Implement changing of passwords --- api/application.go | 8 ++++---- api/notification.go | 6 +++--- api/user.go | 26 ++++++++++++++++++++------ app.go | 2 +- model/application.go | 8 ++++++-- model/user.go | 9 +++++++-- router/router.go | 9 +++++---- 7 files changed, 46 insertions(+), 22 deletions(-) diff --git a/api/application.go b/api/application.go index d29434f..6d60662 100644 --- a/api/application.go +++ b/api/application.go @@ -27,8 +27,8 @@ type ApplicationDispatcher interface { // ApplicationHandler holds information for processing requests about applications. type ApplicationHandler struct { - DB ApplicationDatabase - Dispatcher ApplicationDispatcher + DB ApplicationDatabase + DP ApplicationDispatcher } func (h *ApplicationHandler) applicationExists(token string) bool { @@ -52,7 +52,7 @@ func (h *ApplicationHandler) CreateApplication(ctx *gin.Context) { log.Printf("User %s will receive notifications for application %s.\n", user.Name, application.Name) - matrixid, err := h.Dispatcher.RegisterApplication(application.Name, user.MatrixID) + matrixid, err := h.DP.RegisterApplication(application.Name, user.MatrixID) if success := successOrAbort(ctx, http.StatusInternalServerError, err); !success { return @@ -86,7 +86,7 @@ func (h *ApplicationHandler) DeleteApplication(ctx *gin.Context) { log.Printf("Deleting application %s.\n", application.Name) - if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.DeregisterApplication(application)); !success { + if success := successOrAbort(ctx, http.StatusInternalServerError, h.DP.DeregisterApplication(application)); !success { return } diff --git a/api/notification.go b/api/notification.go index 859ef17..7aad80e 100644 --- a/api/notification.go +++ b/api/notification.go @@ -23,8 +23,8 @@ type NotificationDispatcher interface { // NotificationHandler holds information for processing requests about notifications. type NotificationHandler struct { - DB NotificationDatabase - Dispatcher NotificationDispatcher + DB NotificationDatabase + DP NotificationDispatcher } // CreateNotification is used to create a new notification for a user. @@ -45,7 +45,7 @@ func (h *NotificationHandler) CreateNotification(ctx *gin.Context) { } notification.Date = time.Now() - if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.SendNotification(application, ¬ification)); !success { + if success := successOrAbort(ctx, http.StatusInternalServerError, h.DP.SendNotification(application, ¬ification)); !success { return } diff --git a/api/user.go b/api/user.go index 6df24be..bcd7449 100644 --- a/api/user.go +++ b/api/user.go @@ -27,10 +27,16 @@ type UserDispatcher interface { DeregisterApplication(a *model.Application) error } +// The CredentialsManager interface for updating credentials. +type CredentialsManager interface { + CreatePasswordHash(password string) []byte +} + // UserHandler holds information for processing requests about users. type UserHandler struct { - DB UserDatabase - Dispatcher ApplicationDispatcher + CM CredentialsManager + DB UserDatabase + DP UserDispatcher } func (h *UserHandler) userExists(name string) bool { @@ -49,6 +55,7 @@ func (h *UserHandler) ensureIsNotLastAdmin(ctx *gin.Context) (int, error) { } // CreateUser creates a new user. +// This method assumes that the requesting user has privileges. func (h *UserHandler) CreateUser(ctx *gin.Context) { var externalUser model.ExternalUserWithCredentials @@ -71,6 +78,8 @@ func (h *UserHandler) CreateUser(ctx *gin.Context) { } // DeleteUser deletes a user with a certain ID. +// +// This method assumes that the requesting user has privileges. func (h *UserHandler) DeleteUser(ctx *gin.Context) { var deleteUser model.DeleteUser @@ -99,7 +108,7 @@ func (h *UserHandler) DeleteUser(ctx *gin.Context) { } for _, app := range applications { - if success := successOrAbort(ctx, http.StatusInternalServerError, h.Dispatcher.DeregisterApplication(&app)); !success { + if success := successOrAbort(ctx, http.StatusInternalServerError, h.DP.DeregisterApplication(&app)); !success { return } } @@ -112,6 +121,9 @@ func (h *UserHandler) DeleteUser(ctx *gin.Context) { } // UpdateUser updates a user with a certain ID. +// +// 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) { var updateUser model.UpdateUser @@ -136,11 +148,13 @@ func (h *UserHandler) UpdateUser(ctx *gin.Context) { log.Printf("Updating user %s.\n", user.Name) - // If users can later update their own user, make sure they cannot give themselves privileges. + if user.MatrixID != updateUser.MatrixID { + // TODO: Update correspondent in rooms of applications. + } + // TODO: Handle unbound members. - // TODO: Allow updating of password. - // TODO: Update rooms of applications when the user's MatrixID changes. user.Name = updateUser.Name + user.PasswordHash = h.CM.CreatePasswordHash(updateUser.Password) user.MatrixID = updateUser.MatrixID user.IsAdmin = updateUser.IsAdmin diff --git a/app.go b/app.go index df83ca2..d59585b 100644 --- a/app.go +++ b/app.go @@ -55,7 +55,7 @@ func main() { setupCleanup(db, dp) - engine := router.Create(c.Debug, db, dp) + engine := router.Create(c.Debug, cm, db, dp) runner.Run(engine, c.HTTP.ListenAddress, c.HTTP.Port) } diff --git a/model/application.go b/model/application.go index 8a3b842..7523029 100644 --- a/model/application.go +++ b/model/application.go @@ -14,13 +14,17 @@ type CreateApplication struct { Name string `form:"name" query:"name" json:"name" binding:"required"` } +type applicationIdentification struct { + ID uint `uri:"id" binding:"required"` +} + // DeleteApplication is used to process queries for deleting applications. type DeleteApplication struct { - ID uint `uri:"id"` + applicationIdentification } // UpdateApplication is used to process queries for updating applications. type UpdateApplication struct { - ID uint `uri:"id" binding:"required"` + applicationIdentification Name string `json:"name"` } diff --git a/model/user.go b/model/user.go index 5748796..a1c55ce 100644 --- a/model/user.go +++ b/model/user.go @@ -67,15 +67,20 @@ func (u *User) IntoExternalUser() *ExternalUser { } } +type userIdentification struct { + ID uint `uri:"id" binding:"required"` +} + // DeleteUser is used to process queries for deleting users. type DeleteUser struct { - ID uint `uri:"id"` + userIdentification } // UpdateUser is used to process queries for updating users. type UpdateUser struct { - ID uint `uri:"id" binding:"required"` + userIdentification Name string `json:"name"` + Password string `json:"password"` IsAdmin bool `json:"is_admin"` MatrixID string `json:"matrix_id"` } diff --git a/router/router.go b/router/router.go index 1bcc072..b6d490f 100644 --- a/router/router.go +++ b/router/router.go @@ -5,6 +5,7 @@ import ( "github.com/eikendev/pushbits/api" "github.com/eikendev/pushbits/authentication" + "github.com/eikendev/pushbits/authentication/credentials" "github.com/eikendev/pushbits/database" "github.com/eikendev/pushbits/dispatcher" @@ -13,7 +14,7 @@ import ( ) // Create a Gin engine and setup all routes. -func Create(debug bool, db *database.Database, dp *dispatcher.Dispatcher) *gin.Engine { +func Create(debug bool, cm *credentials.Manager, db *database.Database, dp *dispatcher.Dispatcher) *gin.Engine { log.Println("Setting up HTTP routes.") if !debug { @@ -22,9 +23,9 @@ func Create(debug bool, db *database.Database, dp *dispatcher.Dispatcher) *gin.E auth := authentication.Authenticator{DB: db} - applicationHandler := api.ApplicationHandler{DB: db, Dispatcher: dp} - notificationHandler := api.NotificationHandler{DB: db, Dispatcher: dp} - userHandler := api.UserHandler{DB: db, Dispatcher: dp} + applicationHandler := api.ApplicationHandler{DB: db, DP: dp} + notificationHandler := api.NotificationHandler{DB: db, DP: dp} + userHandler := api.UserHandler{CM: cm, DB: db, DP: dp} r := gin.Default()