Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Roles#1789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
Bibo-Joshi wants to merge22 commits intomasterfromroles
Closed

Roles#1789

Bibo-Joshi wants to merge22 commits intomasterfromroles

Conversation

Bibo-Joshi
Copy link
Member

@Bibo-JoshiBibo-Joshi commentedFeb 21, 2020
edited
Loading

This PR adds the functionality of restricting access to handlers to

  • specified users (by id)
  • specified chats (by id)
  • chat admins
  • chat creators

Builds upon#1757 (see below)
Closes#1151,#1562

Example usage:

updater=Updater('TOKEN')dp=updater.dispatcherroles=updater.dispatcher.rolesroles.add_admin('authors_user_id')roles.add_role(name='my_role_1')my_role_1=roles['my_role_1']roles.add_role(name='my_role_2',parent_roles=roles['my_role_1'])my_role_2=roles['my_role_2']defadd_to_my_role_2(update,context):user=update.effective_usercontext.roles['my_role_2'].add_member(user.id)defadd_to_my_role_1(update,context):user_id=update.message.textcontext.roles['my_role_1'].add_member(user_id)....# Anyone can add themself to my_role_2dp.add_handler(TypeHandler(Update,add_to_my_role_2))# Only the admin can add users to my_role_1dp.add_handler(MessageHandler(Filters.message,add_to_my_role_1,roles=roles.ADMINS))# This will be accessable by my_role_2, my_role_1 and the admindp.add_handler(SomeHandler(...,roles=my_role_2))# This will be accessable by my_role_1 and the admindp.add_handler(SomeHandler(...,roles=my_role_1))# This will be accessable by anyone except my_role_1 and my_role_2dp.add_handler(SomeHandler(...,roles=~my_role_1))# This will be accessable by users, who are in my_role_2 bot not in my_role_1dp.add_handler(SomeHandler(...,roles=~my_role_1&my_role_2))# This will be accessable only by the admins of the group the update was sent indp.add_handler(SomeHandler(...,roles=roles.CHAT_ADMINS))# This will be accessable only by the creator of the group the update was sent indp.add_handler(SomeHandler(...,roles=roles.CHAT_CREATOR))# You can compare the roles regarding hierarchy:roles.ADMINS>=roles['my_role_1']#Trueroles.ADMINS>=roles['my_role_2']#Trueroles['my_role_1']<roles['my_role_2']#Falseroles.ADMINS>=Role(...)#False, since neither of those is a parent of the other

How does it work

Added Classes

Role

  • Inherits fromFilters.user (This is, whereAllow updating user_ids/usernames of a running filters.user #1757 comes in. Can be changed to inherinting fromBaseFilter if the reviewer want that)
  • Can be combined by bitwise operations (This is why I'm Inheriting fromFilters)
  • Can be compared w.r.t. hierarchy. E.g. in above example:my_role_1 > my_role_2
  • Dynamically add/kick members

Roles

A container for multiple roles

  • Inherits fromdict to allow accessing the roles byroles['role_name']
  • Roles.ADMINS is parent to every role
  • Roles.CHAT_ADMINS,Roles.CHAT_CREATOR as shortcuts for restricting acces in group chats
  • Dynamically add/remove admins and roles

Integration with handlers

The base classHandler now has a__new__ method that makes sure, thatcheck_update is called only, if the roles checked out. Alternatives approaches would be

  • MakeHandler.check_update check the roles directly and callsuper().check_updater in all the specific handlers. This means that custom handlers would have to change theircheck_update implementation. Then again, they may have to be adjusted to accept theroles argument anyway
  • Add a methoHandler.check_update_with_roles that callesHandler.check_update after checking the roles. In the current code base, replace all calls tocheck_update withcheck_update_with_role. This would leave current implementation ofcheck_update untouched.

Integration with dispatcher

  • Dispatcher.roles is theRoles instance managing the roles
  • Dispatcher.roles is available ascontext.roles to allow editing roles in callbacks
  • store_roles is added to persistence to allow keeping track of roles over restarts. I know that adding stuff to persistence should be done with care. But if we want dynamic access control (and I do), we need persistence here.

ToDo

  • Add roles to newPollAnswerHandler. AsPoll updates have neither user nor chat, we don't need roles withPollHandler

  • Cache chat admins and creators (timeout is customizable viaroles.CHAT_ADMINS.timeout = ...)

  • Handle private chats correctly withroles.CHAT_ADMINS/CHAT_CREATOR (this is as easy if checkingchat.id == user.id)

  • When merged, we should create a wiki page. Important points to mention there:

    • Hard codingdp.roles.add_admin(id) willalways add the user to admins on start up with persistence, even if they are removed by dynamic access control. Thus, only the author of the bot should be hard coded as admin.
    • Admins shouldonly be inroles.ADMINS, else they might be excluded byroles=~roles['my_role'], if they are inmy_role
    • Hard codingdp.roles.add_role(name='my_group') will lead toValueError on restart with persistence because after restoring the data, the rolemy_group will already be set. Use'my_group' in dp.roles to check for that before adding the group.
  • Depending on how long it will take to merge this:

@Bibo-JoshiBibo-Joshi added this to the12.5 milestoneFeb 21, 2020
@Bibo-Joshi
Copy link
MemberAuthor

Codacy mainly complains about missing docs for methods which are intended for internal use only. IMHO we can ignore that.

@Bibo-JoshiBibo-Joshi mentioned this pull requestMar 23, 2020
6 tasks
Bibo-Joshiand others added21 commitsApril 7, 2020 14:44
Add roles to all handlersmake roles name a property to ensure its up to dateAdd roles to PrefixHandlerMake Roles inherit from dictAdjust tests for rolesAdjust handlers __new__ to work with conversationhandlerRemove roles from StringCommand/RegexHandler - doesnt make sense thereRemove roles from TypeHandler - doesnt make sense thereadd handler tests
Rework equality stuff once againImprove equality tests for role
Fixes for chat_ids handlingAdjust CH test for chat_ids
Adjust tests for py3.5 (dicts are not ordered there)Adjust tests for py3.5 V2Just skip on py3.5 …
Add docs about cache timeout for Roles.CHAT_ADMINS
Use __repr__ instead of name property
Update BasePersistence docstringRefine handler tests
# Conflicts:#telegram/ext/dispatcher.py#tests/test_persistence.py
@Bibo-Joshi
Copy link
MemberAuthor

As suggested by@tsnoam I had a look at third party ACL and RBAC implementations. Though there are some libraries that seem well maintained, they mostly seem

  • tailored for website applications
  • not to allow for easy dynamic editing of roles
  • have rather involved persistence integrations

My impression may well be based on lack of expertise, but to me it seems cleaner to have a custom implementation tailored to our needs than to rely on those third party implementations.

@Bibo-JoshiBibo-Joshi removed this from the12.6 milestoneJun 12, 2020
@tsnoam
Copy link
Member

just a thought:
would it be possible to implement roles using decorators?
user who wants a handler with a certain role, can just decorate it with something to do that magic.

classic for a contrib repo, btw ;-)

@Bibo-Joshi
Copy link
MemberAuthor

classic for a contrib repo, btw ;-)

decorators? yeah, sounds about right

just a thought:
would it be possible to implement roles using decorators?
user who wants a handler with a certain role, can just decorate it with something to do that magic.

one would need to decorate every callback … We just made a point not to use decorators on callbacks with deprecating @run_async :D
but one could think of a Handler-Wrapper:

class RolesHandlerWrapper:    def __init__(base_class, roles, *args, **kwargs):        super().__init__(*args, **kwargs)        self.roles = roles    def check_update(update):       if self.roles(update):            return super().check_update(update)       return False

@tsnoam
Copy link
Member

@Bibo-Joshi
I don't like decorators.
But contrib? That can be a jungle AFAIC.

I like your idea for a HandlerWrapper. That can be contrib as well.

Bottom line: contrib.

@Bibo-Joshi
Copy link
MemberAuthor

Closing to be revisited after#1912 is done. v13 changed so much, I can probably start from scratch anyway :D

@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsOct 17, 2020
@Bibo-JoshiBibo-Joshi deleted the roles branchOctober 27, 2020 16:44
@Bibo-JoshiBibo-Joshi added 🔌 enhancementpr description: enhancement and removed enhancement labelsNov 3, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@PoolitzerPoolitzerAwaiting requested review from Poolitzer

Assignees
No one assigned
Labels
🔌 enhancementpr description: enhancement
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

Feature suggestion: Authentication
2 participants
@Bibo-Joshi@tsnoam

[8]ページ先頭

©2009-2025 Movatter.jp