mirror of
https://github.com/apache/superset.git
synced 2026-07-05 14:25:32 +00:00
71 lines
3.1 KiB
Python
71 lines
3.1 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
"""Integration tests asserting the password-complexity policy is wired into
|
|
Flask-AppBuilder's User REST API (not just the validator function itself)."""
|
|
|
|
from superset import db, security_manager
|
|
from tests.integration_tests.base_tests import SupersetTestCase
|
|
from tests.integration_tests.constants import ADMIN_USERNAME
|
|
|
|
USERS_API_URI = "/api/v1/security/users/"
|
|
|
|
|
|
class TestPasswordComplexityUserApi(SupersetTestCase):
|
|
"""Exercise the real FAB ``/api/v1/security/users/`` path so that a future
|
|
Flask-AppBuilder bump that drops enforcement fails these tests."""
|
|
|
|
def _user_payload(self, password: str) -> dict[str, object]:
|
|
"""Build a valid user-creation payload with the given password."""
|
|
gamma_role = security_manager.find_role("Gamma")
|
|
return {
|
|
"active": True,
|
|
"email": "pw_complexity_test@example.com",
|
|
"first_name": "Password",
|
|
"last_name": "Complexity",
|
|
"username": "pw_complexity_test_user",
|
|
"roles": [gamma_role.id],
|
|
"password": password,
|
|
}
|
|
|
|
def test_create_user_rejects_short_password(self):
|
|
"""A too-short password is rejected by the User REST API with a 400."""
|
|
self.login(ADMIN_USERNAME)
|
|
rv = self.client.post(USERS_API_URI, json=self._user_payload("Ab1!"))
|
|
assert rv.status_code == 400
|
|
assert b"at least" in rv.data
|
|
assert security_manager.find_user(username="pw_complexity_test_user") is None
|
|
|
|
def test_create_user_rejects_common_password(self):
|
|
"""A blocklisted common password is rejected by the User REST API."""
|
|
self.login(ADMIN_USERNAME)
|
|
rv = self.client.post(USERS_API_URI, json=self._user_payload("password123"))
|
|
assert rv.status_code == 400
|
|
assert b"too common" in rv.data
|
|
assert security_manager.find_user(username="pw_complexity_test_user") is None
|
|
|
|
def test_create_user_accepts_compliant_password(self):
|
|
"""A password satisfying the policy is accepted by the User REST API."""
|
|
self.login(ADMIN_USERNAME)
|
|
rv = self.client.post(
|
|
USERS_API_URI, json=self._user_payload("correct-horse-battery")
|
|
)
|
|
assert rv.status_code == 201
|
|
user = security_manager.find_user(username="pw_complexity_test_user")
|
|
assert user is not None
|
|
db.session.delete(user)
|
|
db.session.commit()
|