def test_api_user_can_update_password_if_none_not_if_set():
    """Can a user set their password if they do not currently have a password"""
    app = create_ctfd()
    with app.app_context():
        # Create a user with a null password. Use raw SQL to bypass SQLAlchemy validates
        register_user(app, name="testuser", email="user@examplectf.com")
        db.session.execute("UPDATE users SET password=NULL WHERE name='testuser'")
        user = Users.query.filter_by(name="testuser").first()
        db.session.commit()
        assert user.password is None

        with app.test_client() as client:
            # Login as user
            with client.session_transaction() as sess:
                sess["id"] = user.id
            r = client.get("/api/v1/users/me", json=True)
            assert r.status_code == 200

            # Test that user can change password
            user = Users.query.filter_by(name="testuser").first()
            assert user.password is None
            data = {"password": "12345", "confirm": "password"}
            r = client.patch("/api/v1/users/me", json=data)
            assert r.status_code == 200

            # Verify password is now set
            user = Users.query.filter_by(name="testuser").first()
            assert verify_password(plaintext="12345", ciphertext=user.password)

            # Verify that password cannot be changed
            data = {"password": "noset", "confirm": "password"}
            r = client.patch("/api/v1/users/me", json=data)
            resp = r.get_json()
            assert resp["errors"]["confirm"] == ["Your previous password is incorrect"]
            assert r.status_code == 400

            # Verify a regular user cannot patch another user
            register_user(
                app,
                name="testuser2",
                email="user2@examplectf.com",
                password="testinguser",
            )
            testuser = Users.query.filter_by(name="testuser2").first()
            assert verify_password(
                plaintext="testinguser", ciphertext=testuser.password
            )
            data = {"password": "password", "confirm": "password"}
            r = client.patch("/api/v1/users/3", json=data)
            assert r.status_code == 403
            testuser = Users.query.filter_by(name="testuser2").first()
            assert verify_password(
                plaintext="testinguser", ciphertext=testuser.password
            )

    destroy_ctfd(app)
Can a user set their password if they do not currently have a password
tests/api/v1/users/test_users.py