]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: User password should be optional
authorRicardo Marques <rimarques@suse.com>
Mon, 17 Sep 2018 11:03:37 +0000 (12:03 +0100)
committerRicardo Marques <rimarques@suse.com>
Wed, 19 Sep 2018 12:49:22 +0000 (13:49 +0100)
Fixes: https://tracker.ceph.com/issues/36031
Signed-off-by: Ricardo Marques <rimarques@suse.com>
doc/mgr/dashboard.rst
qa/tasks/mgr/dashboard/test_auth.py
qa/tasks/mgr/dashboard/test_user.py
src/pybind/mgr/dashboard/controllers/user.py
src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.ts
src/pybind/mgr/dashboard/services/access_control.py

index 66f6c41bb870c87f3559f54ae17d45003426b813..8b9ae7628c8d3cc8d241efb3eb6d5c93dd871029 100644 (file)
@@ -363,7 +363,7 @@ We provide a set of CLI commands to manage user accounts:
 
 - *Create User*::
 
-  $ ceph dashboard ac-user-create <username> <password> [<rolename>] [<name>] [<email>]
+  $ ceph dashboard ac-user-create <username> [<password>] [<rolename>] [<name>] [<email>]
 
 - *Delete User*::
 
index 04344050207dc4eddf2fb66c55e0cf2c7562a5b3..0921b7d9b4f6f5bdb5872ce8fe16246a0ede1a6c 100644 (file)
@@ -76,6 +76,17 @@ class AuthTest(DashboardTestCase):
             "detail": "Invalid credentials"
         })
 
+    def test_login_without_password(self):
+        self.create_user('admin2', '', ['administrator'])
+        self._post("/api/auth", {'username': 'admin2', 'password': ''})
+        self.assertStatus(400)
+        self.assertJsonBody({
+            "component": "auth",
+            "code": "invalid_credentials",
+            "detail": "Invalid credentials"
+        })
+        self.delete_user('admin2')
+
     def test_logout(self):
         self._post("/api/auth", {'username': 'admin', 'password': 'admin'})
         self._delete("/api/auth")
index 187d1a25d601e0264bf4578c15339b2e7cd6f958..57521da7de4463564cc4e7345b3fd4fa7b9232b3 100644 (file)
@@ -75,15 +75,6 @@ class UserTest(DashboardTestCase):
         self.assertError(code='username_already_exists',
                          component='user')
 
-    def test_create_user_no_password(self):
-        self._create_user(username='user1',
-                          name='My Name',
-                          email='admin@email.com',
-                          roles=['administrator'])
-        self.assertStatus(400)
-        self.assertError(code='password_required',
-                         component='user')
-
     def test_create_user_invalid_role(self):
         self._create_user(username='user1',
                           password='mypassword',
index b49872f0778556ccd930e222ff50ea46431794e5..a0671c5fe1cfd0bb3317dc1a4c078302c7561a58 100644 (file)
@@ -47,10 +47,6 @@ class User(RESTController):
             raise DashboardException(msg='Username is required',
                                      code='username_required',
                                      component='user')
-        if not password:
-            raise DashboardException(msg='Password is required',
-                                     code='password_required',
-                                     component='user')
         user_roles = None
         if roles:
             user_roles = User._get_user_roles(roles)
index a21232eb2847d7c6fbf112a15a777e4cdef2abab..f42d8e7c6e006e2ea5311ae87363453ef46b6317 100644 (file)
@@ -43,8 +43,6 @@
           <label i18n
                  class="control-label col-sm-3"
                  for="name">Password
-            <span class="required"
-                  *ngIf="mode !== userFormMode.editing"></span>
           </label>
           <div class="col-sm-9">
             <div class="input-group">
@@ -75,8 +73,6 @@
           <label i18n
                  class="control-label col-sm-3"
                  for="name">Confirm password
-            <span class="required"
-                  *ngIf="mode !== userFormMode.editing"></span>
           </label>
           <div class="col-sm-9">
             <div class="input-group">
index b7a7f8a5f8885e0f34c422e6be70b5692964be9a..9d21da358ebd5bd405c79a871fe129cb2619296b 100644 (file)
@@ -88,12 +88,8 @@ describe('UserFormComponent', () => {
     it('should validate username required', () => {
       form.get('username').setValue('');
       expect(form.get('username').hasError('required')).toBeTruthy();
-    });
-
-    it('should validate password required', () => {
-      ['password', 'confirmpassword'].forEach((key) =>
-        expect(form.get(key).hasError('required')).toBeTruthy()
-      );
+      form.get('username').setValue('user1');
+      expect(form.get('username').hasError('required')).toBeFalsy();
     });
 
     it('should validate password match', () => {
@@ -109,6 +105,13 @@ describe('UserFormComponent', () => {
       expect(form.get('email').hasError('email')).toBeTruthy();
     });
 
+    it('should validate all required fields', () => {
+      form.get('username').setValue('');
+      expect(form.valid).toBeFalsy();
+      form.get('username').setValue('user1');
+      expect(form.valid).toBeTruthy();
+    });
+
     it('should set mode', () => {
       expect(component.mode).toBeUndefined();
     });
@@ -196,13 +199,6 @@ describe('UserFormComponent', () => {
       expect(component.mode).toBe('editing');
     });
 
-    it('should validate password not required', () => {
-      ['password', 'confirmpassword'].forEach((key) => {
-        form.get(key).setValue('');
-        expect(form.get(key).hasError('required')).toBeFalsy();
-      });
-    });
-
     it('should alert if user is removing needed role permission', () => {
       spyOn(TestBed.get(AuthStorageService), 'getUsername').and.callFake(() => user.username);
       let modalBodyTpl = null;
index c1a7be7e976223e4e64e017c801cc5e331d5523c..1b323f68e8cc776d771d820954ed78c330878fe0 100644 (file)
@@ -83,21 +83,10 @@ export class UserFormComponent implements OnInit {
     });
     if (this.mode === this.userFormMode.editing) {
       this.initEdit();
-    } else {
-      this.initAdd();
     }
   }
 
-  initAdd() {
-    ['password', 'confirmpassword'].forEach((controlName) =>
-      this.userForm.get(controlName).setValidators([Validators.required])
-    );
-  }
-
   initEdit() {
-    ['password', 'confirmpassword'].forEach((controlName) =>
-      this.userForm.get(controlName).setValidators([])
-    );
     this.disableForEdit();
     this.route.params.subscribe((params: { username: string }) => {
       const username = params.username;
index 10eb705706b79b456c6e8d91a62c386ee0b3c3d3..61a4d380e1ac366b27ea8a89af0ed32e066deebf 100644 (file)
@@ -19,6 +19,8 @@ from ..exceptions import RoleAlreadyExists, RoleDoesNotExist, ScopeNotValid, \
 
 # password hashing algorithm
 def password_hash(password, salt_password=None):
+    if not password:
+        return None
     if not salt_password:
         salt_password = bcrypt.gensalt()
     else:
@@ -381,7 +383,7 @@ ACCESS_CONTROL_COMMANDS = [
     {
         'cmd': 'dashboard ac-user-create '
                'name=username,type=CephString '
-               'name=password,type=CephString '
+               'name=password,type=CephString,req=false '
                'name=rolename,type=CephString,req=false '
                'name=name,type=CephString,req=false '
                'name=email,type=CephString,req=false',
@@ -545,7 +547,7 @@ Username and password updated''', ''
 
     elif cmd['prefix'] == 'dashboard ac-user-create':
         username = cmd['username']
-        password = cmd['password']
+        password = cmd['password'] if 'password' in cmd else None
         rolename = cmd['rolename'] if 'rolename' in cmd else None
         name = cmd['name'] if 'name' in cmd else None
         email = cmd['email'] if 'email' in cmd else None
@@ -669,9 +671,10 @@ class LocalAuthenticator(object):
     def authenticate(self, username, password):
         try:
             user = ACCESS_CTRL_DB.get_user(username)
-            pass_hash = password_hash(password, user.password)
-            if pass_hash == user.password:
-                return user.permissions_dict()
+            if user.password:
+                pass_hash = password_hash(password, user.password)
+                if pass_hash == user.password:
+                    return user.permissions_dict()
         except UserDoesNotExist:
             logger.debug("User '%s' does not exist", username)
         return None