From e65d132b3dc40eea45560db2583d96de91a5dde1 Mon Sep 17 00:00:00 2001 From: Anthony Lapenna Date: Mon, 28 Aug 2017 20:59:13 +0200 Subject: [PATCH] feat(init-admin): allow to specify a username for the initial admin account (#1160) --- api/errors.go | 6 +- api/http/handler/user.go | 33 +++- app/app.js | 39 +++- app/components/auth/auth.html | 78 ++------ app/components/auth/authController.js | 183 ++++++++---------- app/components/initAdmin/initAdmin.html | 80 ++++++++ .../initAdmin/initAdminController.js | 33 ++++ .../initEndpoint.html} | 104 ++++++---- .../initEndpointController.js} | 73 +++---- app/services/api/userService.js | 21 ++ assets/css/app.css | 4 +- index.html | 7 +- 12 files changed, 385 insertions(+), 276 deletions(-) create mode 100644 app/components/initAdmin/initAdmin.html create mode 100644 app/components/initAdmin/initAdminController.js rename app/components/{endpointInit/endpointInit.html => initEndpoint/initEndpoint.html} (59%) rename app/components/{endpointInit/endpointInitController.js => initEndpoint/initEndpointController.js} (51%) diff --git a/api/errors.go b/api/errors.go index bf5f5517a..aefd967b7 100644 --- a/api/errors.go +++ b/api/errors.go @@ -13,8 +13,10 @@ const ( const ( ErrUserNotFound = Error("User not found") ErrUserAlreadyExists = Error("User already exists") - ErrInvalidUsername = Error("Invalid username. White spaces are not allowed.") - ErrAdminAlreadyInitialized = Error("Admin user already initialized") + ErrInvalidUsername = Error("Invalid username. White spaces are not allowed") + ErrAdminAlreadyInitialized = Error("An administrator user already exists") + ErrCannotRemoveAdmin = Error("Cannot remove the default administrator account") + ErrAdminCannotRemoveSelf = Error("Cannot remove your own user account. Contact another administrator") ) // Team errors. diff --git a/api/http/handler/user.go b/api/http/handler/user.go index 7aa4e11c9..72952737d 100644 --- a/api/http/handler/user.go +++ b/api/http/handler/user.go @@ -82,6 +82,7 @@ type ( } postAdminInitRequest struct { + Username string `valid:"required"` Password string `valid:"required"` } ) @@ -358,10 +359,14 @@ func (handler *UserHandler) handlePostAdminInit(w http.ResponseWriter, r *http.R return } - user, err := handler.UserService.UserByUsername("admin") - if err == portainer.ErrUserNotFound { + users, err := handler.UserService.UsersByRole(portainer.AdministratorRole) + if err != nil { + httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger) + return + } + if len(users) == 0 { user := &portainer.User{ - Username: "admin", + Username: req.Username, Role: portainer.AdministratorRole, } user.Password, err = handler.CryptoService.Hash(req.Password) @@ -375,11 +380,7 @@ func (handler *UserHandler) handlePostAdminInit(w http.ResponseWriter, r *http.R httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger) return } - } else if err != nil { - httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger) - return - } - if user != nil { + } else { httperror.WriteErrorResponse(w, portainer.ErrAdminAlreadyInitialized, http.StatusConflict, handler.Logger) return } @@ -396,6 +397,22 @@ func (handler *UserHandler) handleDeleteUser(w http.ResponseWriter, r *http.Requ return } + if userID == 1 { + httperror.WriteErrorResponse(w, portainer.ErrCannotRemoveAdmin, http.StatusForbidden, handler.Logger) + return + } + + tokenData, err := security.RetrieveTokenData(r) + if err != nil { + httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger) + return + } + + if tokenData.ID == portainer.UserID(userID) { + httperror.WriteErrorResponse(w, portainer.ErrAdminCannotRemoveSelf, http.StatusForbidden, handler.Logger) + return + } + _, err = handler.UserService.User(portainer.UserID(userID)) if err == portainer.ErrUserNotFound { diff --git a/app/app.js b/app/app.js index d7774719f..059b41344 100644 --- a/app/app.js +++ b/app/app.js @@ -34,11 +34,12 @@ angular.module('portainer', [ 'docker', 'endpoint', 'endpointAccess', - 'endpointInit', 'endpoints', 'events', 'image', 'images', + 'initAdmin', + 'initEndpoint', 'main', 'network', 'networks', @@ -321,6 +322,33 @@ angular.module('portainer', [ } } }) + .state('init', { + abstract: true, + url: '/init', + views: { + 'content@': { + template: '
' + } + } + }) + .state('init.endpoint', { + url: '/endpoint', + views: { + 'content@': { + templateUrl: 'app/components/initEndpoint/initEndpoint.html', + controller: 'InitEndpointController' + } + } + }) + .state('init.admin', { + url: '/admin', + views: { + 'content@': { + templateUrl: 'app/components/initAdmin/initAdmin.html', + controller: 'InitAdminController' + } + } + }) .state('docker', { url: '/docker/', views: { @@ -373,15 +401,6 @@ angular.module('portainer', [ } } }) - .state('endpointInit', { - url: '/init/endpoint', - views: { - 'content@': { - templateUrl: 'app/components/endpointInit/endpointInit.html', - controller: 'EndpointInitController' - } - } - }) .state('events', { url: '/events/', views: { diff --git a/app/components/auth/auth.html b/app/components/auth/auth.html index 8668d328a..fe53cc0b5 100644 --- a/app/components/auth/auth.html +++ b/app/components/auth/auth.html @@ -1,92 +1,38 @@
-
+
- +
- -
-
- - - -
-
- -
+
-