From 019ce80fc529a0437984fdc3d1ab6916f34dd594 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 11 Jan 2021 22:33:36 +0100 Subject: [PATCH] fix: don't allow to remove root user --- errors/errors.go | 1 + frontend/src/utils/vue.js | 4 ++-- frontend/src/views/settings/User.vue | 2 +- http/users.go | 4 ++-- http/utils.go | 2 ++ users/storage.go | 20 ++++++++++++++------ 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/errors/errors.go b/errors/errors.go index c79e3783..5ec364c0 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -17,4 +17,5 @@ var ( ErrPermissionDenied = errors.New("permission denied") ErrInvalidRequestParams = errors.New("invalid request params") ErrSourceIsParent = errors.New("source is parent") + ErrRootUserDeletion = errors.New("user with id 1 can't be deleted") ) diff --git a/frontend/src/utils/vue.js b/frontend/src/utils/vue.js index 6cfe52b9..313b60dd 100644 --- a/frontend/src/utils/vue.js +++ b/frontend/src/utils/vue.js @@ -26,14 +26,14 @@ Vue.prototype.$showSuccess = (message) => { })).show() } -Vue.prototype.$showError = (error) => { +Vue.prototype.$showError = (error, displayReport = true) => { let btns = [ Noty.button(i18n.t('buttons.close'), '', function () { n.close() }) ] - if (!disableExternal) { + if (!disableExternal && displayReport) { btns.unshift(Noty.button(i18n.t('buttons.reportIssue'), '', function () { window.open('https://github.com/filebrowser/filebrowser/issues/new/choose') })) diff --git a/frontend/src/views/settings/User.vue b/frontend/src/views/settings/User.vue index 01581d21..3cff063c 100644 --- a/frontend/src/views/settings/User.vue +++ b/frontend/src/views/settings/User.vue @@ -115,7 +115,7 @@ export default { this.$router.push({ path: '/settings/users' }) this.$showSuccess(this.$t('settings.userDeleted')) } catch (e) { - this.$showError(e) + (e.message === "403") ? this.$showError(this.$t("errors.forbidden"), false) : this.$showError(e) } }, async save (event) { diff --git a/http/users.go b/http/users.go index b03c9e09..4e29c46a 100644 --- a/http/users.go +++ b/http/users.go @@ -99,8 +99,8 @@ var userGetHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request var userDeleteHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { err := d.store.Users.Delete(d.raw.(uint)) - if err == errors.ErrNotExist { - return http.StatusNotFound, err + if err != nil { + return errToStatus(err), err } return http.StatusOK, nil diff --git a/http/utils.go b/http/utils.go index a8eac8ae..ce605b36 100644 --- a/http/utils.go +++ b/http/utils.go @@ -40,6 +40,8 @@ func errToStatus(err error) int { return http.StatusForbidden case errors.Is(err, libErrors.ErrInvalidRequestParams): return http.StatusBadRequest + case errors.Is(err, libErrors.ErrRootUserDeletion): + return http.StatusForbidden default: return http.StatusInternalServerError } diff --git a/users/storage.go b/users/storage.go index f9b3aa80..76a8a200 100644 --- a/users/storage.go +++ b/users/storage.go @@ -92,17 +92,25 @@ func (s *Storage) Save(user *User) error { // Delete allows you to delete a user by its name or username. The provided // id must be a string for username lookup or a uint for id lookup. If id // is neither, a ErrInvalidDataType will be returned. -func (s *Storage) Delete(id interface{}) (err error) { +func (s *Storage) Delete(id interface{}) error { switch id := id.(type) { case string: - err = s.back.DeleteByUsername(id) + user, err := s.back.GetBy(id) + if err != nil { + return err + } + if user.ID == 1 { + return errors.ErrRootUserDeletion + } + return s.back.DeleteByUsername(id) case uint: - err = s.back.DeleteByID(id) + if id == 1 { + return errors.ErrRootUserDeletion + } + return s.back.DeleteByID(id) default: - err = errors.ErrInvalidDataType + return errors.ErrInvalidDataType } - - return } // LastUpdate gets the timestamp for the last update of an user.