From b4707e200fab8e8bf1de2cb7504fb9473015d5f5 Mon Sep 17 00:00:00 2001 From: Adora Laura Kalb Date: Thu, 9 May 2024 15:02:43 +0200 Subject: [PATCH] add option for user to disable MFA (#6) --- internal/app/routes.go | 1 + internal/db/multifactor.go | 31 ++++++++++++ internal/web/multifactor-remove.go | 49 +++++++++++++++++++ ...up-multifactor.go => multifactor-setup.go} | 0 views/account.tmpl | 36 +++++++++----- views/setup-multifactor.tmpl | 6 +-- web/add_link.html | 1 - web/main.js | 38 ++++++++++++-- 8 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 internal/web/multifactor-remove.go rename internal/web/{setup-multifactor.go => multifactor-setup.go} (100%) diff --git a/internal/app/routes.go b/internal/app/routes.go index 0172426..4a52314 100644 --- a/internal/app/routes.go +++ b/internal/app/routes.go @@ -12,6 +12,7 @@ func addWebRoutes(f *fiber.App) { f.Get("/admin/account/", web.HandleAdminAccountGet) f.Get("/admin/account/mfasetup", web.HandleAdminAccountMFASetupGet) f.Post("/admin/account/mfasetup", web.HandleAdminAccountMFASetupPost) + f.Delete("/admin/account/mfa", web.HandleAdminAccountMFARemove) f.Get("/admin/login", web.HandleAdminLoginGet) f.Post("/admin/login", web.HandleAdminLoginPost) diff --git a/internal/db/multifactor.go b/internal/db/multifactor.go index 040fb7a..080f602 100644 --- a/internal/db/multifactor.go +++ b/internal/db/multifactor.go @@ -3,10 +3,14 @@ package db import ( "context" "fmt" + "log" "code.lila.network/adoralaura/go-urlsh/models" ) +// UserHasMFA checks the DB if given models.User has MFA enabled. +// Returns (true, nil) if User has MFA enabled, (false, nil) if not. +// (false, error) if a DB error happened func UserHasMFA(user models.User) (bool, error) { numrows, err := models.DB.NewSelect().Model((*models.MFAConfig)(nil)).Where("username = ?", user.UserName).Where("active = ?", true).Count(context.Background()) if err != nil { @@ -33,3 +37,30 @@ func ScratchCodeIsUnique(scratchcode string) bool { } return true } + +// RemoveMFAFromDB removes MFA entries for given models.User from the database. +// Returns nil on success, error otherwise. +func RemoveMFAFromDB(user models.User) error { + hasMfa, err := UserHasMFA(user) + if err != nil { + return fmt.Errorf("[RemoveMFAFromDB] Error removing MFA from DB for user %v: %w", user.UserName, err) + } + + if !hasMfa { + return nil + } + + _, err = models.DB.NewDelete().Model((*models.MFAConfig)(nil)).Where("username = ?", user.UserName).Exec(context.Background()) + if err != nil { + log.Println(err.Error()) + return fmt.Errorf("[RemoveMFAFromDB] Error removing MFA Config from DB for user %v: %w", user.UserName, err) + } + + _, err = models.DB.NewDelete().Model((*models.MFAScratchCode)(nil)).Where("username = ?", user.UserName).Exec(context.Background()) + if err != nil { + log.Println(err.Error()) + return fmt.Errorf("[RemoveMFAFromDB] Error removing MFA scratch codes from DB for user %v: %w", user.UserName, err) + } + + return nil +} diff --git a/internal/web/multifactor-remove.go b/internal/web/multifactor-remove.go new file mode 100644 index 0000000..c8f9a12 --- /dev/null +++ b/internal/web/multifactor-remove.go @@ -0,0 +1,49 @@ +package web + +import ( + "log" + "net/http" + + "code.lila.network/adoralaura/go-urlsh/internal/constants" + "code.lila.network/adoralaura/go-urlsh/internal/db" + "code.lila.network/adoralaura/go-urlsh/internal/misc" + "github.com/gofiber/fiber/v2" +) + +// HandleAdminAccountMFARemove is a DELETE endpoint that handles the deletion +// of the logged in users MFA configuration. +// +// Returns HTTP 401 if no valid user cookie, HTTP 400 if no MFA is configured for the user, +// HTTP 500 if a DB error happened or HTTP 204 if the deletion request succeeded. +func HandleAdminAccountMFARemove(c *fiber.Ctx) error { + + if !db.IsCookieValid(c.Cookies(constants.LoginCookieName, "")) { + c.Status(http.StatusUnauthorized) + return nil + } + + user, err := db.GetUserFromCookie(c.Cookies(constants.LoginCookieName)) + if err != nil { + log.Println(err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + hasMfa, err := db.UserHasMFA(user) + if err != nil { + log.Println(err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + if !hasMfa { + return misc.New400Error() + } + + err = db.RemoveMFAFromDB(user) + if err != nil { + log.Println(err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + c.Status(fiber.StatusNoContent) + return nil +} diff --git a/internal/web/setup-multifactor.go b/internal/web/multifactor-setup.go similarity index 100% rename from internal/web/setup-multifactor.go rename to internal/web/multifactor-setup.go diff --git a/views/account.tmpl b/views/account.tmpl index 5c97cbc..418b754 100644 --- a/views/account.tmpl +++ b/views/account.tmpl @@ -11,9 +11,15 @@