diff --git a/api/http/handler/users/user_delete.go b/api/http/handler/users/user_delete.go index df72fe673..e192cd055 100644 --- a/api/http/handler/users/user_delete.go +++ b/api/http/handler/users/user_delete.go @@ -1,6 +1,7 @@ package users import ( + "errors" "net/http" httperror "github.com/portainer/libhttp/error" @@ -17,6 +18,10 @@ func (handler *Handler) userDelete(w http.ResponseWriter, r *http.Request) *http return &httperror.HandlerError{http.StatusBadRequest, "Invalid user identifier route variable", err} } + if userID == 1 { + return &httperror.HandlerError{http.StatusForbidden, "Cannot remove the initial admin account", errors.New("Cannot remove the initial admin account")} + } + tokenData, err := security.RetrieveTokenData(r) if err != nil { return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user authentication token", err} diff --git a/app/portainer/components/datatables/users-datatable/usersDatatable.html b/app/portainer/components/datatables/users-datatable/usersDatatable.html index 188dc0ba7..06e5f99cd 100644 --- a/app/portainer/components/datatables/users-datatable/usersDatatable.html +++ b/app/portainer/components/datatables/users-datatable/usersDatatable.html @@ -58,7 +58,7 @@ > - + {{ item.Username }} diff --git a/app/portainer/components/datatables/users-datatable/usersDatatable.js b/app/portainer/components/datatables/users-datatable/usersDatatable.js index a3d38637e..258595c80 100644 --- a/app/portainer/components/datatables/users-datatable/usersDatatable.js +++ b/app/portainer/components/datatables/users-datatable/usersDatatable.js @@ -1,6 +1,9 @@ +import angular from 'angular'; +import UsersDatatableController from './usersDatatableController'; + angular.module('portainer.app').component('usersDatatable', { templateUrl: './usersDatatable.html', - controller: 'GenericDatatableController', + controller: UsersDatatableController, bindings: { titleText: '@', titleIcon: '@', diff --git a/app/portainer/components/datatables/users-datatable/usersDatatableController.js b/app/portainer/components/datatables/users-datatable/usersDatatableController.js new file mode 100644 index 000000000..8b8a60605 --- /dev/null +++ b/app/portainer/components/datatables/users-datatable/usersDatatableController.js @@ -0,0 +1,15 @@ +export default class UsersDatatableController { + /* @ngInject*/ + constructor($controller, $scope) { + const allowSelection = this.allowSelection; + angular.extend(this, $controller('GenericDatatableController', { $scope })); + this.allowSelection = allowSelection.bind(this); + } + + /** + * Override this method to allow/deny selection + */ + allowSelection(item) { + return item.Id !== 1; + } +} diff --git a/app/portainer/views/users/edit/user.html b/app/portainer/views/users/edit/user.html index bfc01dca4..f8b339336 100644 --- a/app/portainer/views/users/edit/user.html +++ b/app/portainer/views/users/edit/user.html @@ -34,7 +34,9 @@
- +
diff --git a/app/portainer/views/users/edit/userController.js b/app/portainer/views/users/edit/userController.js index 93b3e6d9d..12aead65d 100644 --- a/app/portainer/views/users/edit/userController.js +++ b/app/portainer/views/users/edit/userController.js @@ -91,6 +91,12 @@ angular.module('portainer.app').controller('UserController', [ return user && (user.Username !== formValues.username || (formValues.Administrator && user.Role !== 1) || (!formValues.Administrator && user.Role === 1)); } + $scope.isDeleteDisabled = isDeleteDisabled; + function isDeleteDisabled() { + const { user } = $scope; + return user && user.Id === 1; + } + function initView() { $scope.isAdmin = Authentication.isAdmin();