Skip to content

feat(python): expose Permissions and remaining user auth methods#3727

Open
ethanlin01x wants to merge 8 commits into
apache:masterfrom
ethanlin01x:feat/python-permissions
Open

feat(python): expose Permissions and remaining user auth methods#3727
ethanlin01x wants to merge 8 commits into
apache:masterfrom
ethanlin01x:feat/python-permissions

Conversation

@ethanlin01x

Copy link
Copy Markdown
Contributor

Which issue does this PR address?

Closes #3726

Rationale

The Python SDK could create users but not grant them access to anything: create_user hardcoded None for permissions, and update_permissions, change_password, and logout_user` were unexposed.

What changed?

Before, the Python SDK could create users but not grant them access to anything: create_user hardcoded None for permissions, and update_permissions, change_password, and logout_user were unexposed.
Now the Rust Permissions hierarchy is mirrored as PyO3 classes, create_user takes an optional permissions argument, UserInfoDetails exposes a permissions getter, and the three missing methods complete the UserClient surface, with the underlying Rust client handling the wire encoding.

Local Execution

  • Passed
  • Pre-commit hooks ran

AI Usage

Claude was used to help generate and review this PR and all the changes are checked by the human.

@ethanlin01x
ethanlin01x force-pushed the feat/python-permissions branch 2 times, most recently from 63a8908 to 84a9f3b Compare July 21, 2026 16:05
Mirror the Rust Permissions, GlobalPermissions, StreamPermissions, and
TopicPermissions types as PyO3 classes so user permissions can be built
and inspected from Python. Stream and topic dict keys are typed u32 to
match the wire format, so out-of-range IDs fail at construction instead
of being silently truncated. The client methods that consume these
classes follow in the next commits.
create_user hardcoded None for permissions, so every user came out
unprivileged and UserInfoDetails gave no way to inspect grants. Wire the
Permissions argument through create_user and add the permissions getter
so grants round-trip through get_user. The credential helpers shared by
the user tests move to tests/utils.py for the new enforcement tests.
Permissions set at creation were frozen: there was no way to grant,
replace, or revoke them afterwards. update_permissions is a full
replacement and None clears the permissions entirely, matching the Rust
client semantics.
Password rotation required deleting and recreating the user, losing its
id and permissions. change_password verifies the current password
server-side, and a user can rotate its own credentials without any admin
permission.
Sessions could only be abandoned by dropping the connection, leaving the
server-side session authenticated until the socket closed. logout_user
ends the session explicitly; a later login_user on the same client
starts a fresh one.
@ethanlin01x
ethanlin01x force-pushed the feat/python-permissions branch from 84a9f3b to 22bc32c Compare July 21, 2026 16:11
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.66667% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.38%. Comparing base (a5001d3) to head (47fcb74).
⚠️ Report is 8 commits behind head on master.

Files with missing lines Patch % Lines
foreign/python/src/permissions.rs 95.60% 8 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3727      +/-   ##
============================================
+ Coverage     74.34%   74.38%   +0.03%     
  Complexity      950      950              
============================================
  Files          1303     1304       +1     
  Lines        148712   148951     +239     
  Branches     124225   124225              
============================================
+ Hits         110562   110793     +231     
- Misses        34673    34681       +8     
  Partials       3477     3477              
Components Coverage Δ
Rust Core 74.57% <ø> (ø)
Java SDK 62.64% <ø> (ø)
C# SDK 72.28% <ø> (ø)
Python SDK 93.08% <96.66%> (+0.81%) ⬆️
PHP SDK 84.52% <ø> (ø)
Node SDK 92.70% <ø> (ø)
Go SDK 43.08% <ø> (ø)
Files with missing lines Coverage Δ
foreign/python/src/client.rs 99.21% <100.00%> (+0.06%) ⬆️
foreign/python/src/lib.rs 100.00% <100.00%> (ø)
foreign/python/src/user.rs 80.43% <100.00%> (+1.36%) ⬆️
foreign/python/src/permissions.rs 95.60% <95.60%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ethanlin01x
ethanlin01x marked this pull request as ready for review July 21, 2026 16:23
@ethanlin01x

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Jul 21, 2026

@slbotbm slbotbm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first round

#[new]
#[pyo3(signature = (global_=None, streams=None))]
fn new(
#[gen_stub(override_type(type_repr = "GlobalPermissions | None"))] global_: Option<

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why global_? why not global?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global is a reserved keyword in Python.
The trailing underscore follows the PEP 8 convention for names that collide with keywords (like class_). An alternative would be global_permissions, but I kept global_ to mirror the Rust field name. Let me know if you'd prefer the longer name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the following tests:

  • test_all_global_permission_flags_set_together
  • test_all_stream_permission_flags_set_together
  • test_all_topic_permission_flags_set_together

they do not add much to the current test set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us add the following tests:

  • User without manage_users cannot update another user’s permissions.
  • User with manage_users can update another user’s permissions.
  • Failed update leaves target permissions unchanged.
  • calling logout twice fails

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, 41497da

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests, 47fcb74

Comment on lines +194 to +196
async def test_create_user_without_permissions_has_none(
self, iggy_client: IggyClient, unique_name
):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_create_user_without_permissions_has_none is valid but need not be a separate integration test. Add permissions is None assertions to existing test_create_and_get_user.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, da2c17f

@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Jul 23, 2026
@ethanlin01x
ethanlin01x requested a review from slbotbm July 23, 2026 15:56
@ethanlin01x

Copy link
Copy Markdown
Contributor Author

/ready

@github-actions github-actions Bot added S-waiting-on-review PR is waiting on a reviewer and removed S-waiting-on-author PR is waiting on author response labels Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review PR is waiting on a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[python sdk] Expose Permissions and the remaining user auth methods

2 participants