James Foley
James Foley

Reputation: 129

Remove a specific user from a Django Channels group?

I have a couple of Django Channels groups that I use to send various messages to the client with.

Can I remove a specific user from one of these groups, using only the ID of the user that I want to remove?

Another potential option would be to force disconnect the user's connection using just their ID.

Upvotes: 3

Views: 2384

Answers (4)

Ali Rn
Ali Rn

Reputation: 1214

First, you have to save the user's channel_name to their model

and we assume that you had the group_name of channels too

then you can use group_discard for deleting user from group like this:

group_name = 'name_of_channels_group'
user = User.objects.get(id=id)
channel_name = user.channel_name
async_to_sync(self.channel_layer.group_discard)(group_name, channel_name)

https://channels.readthedocs.io/en/stable/topics/channel_layers.html?highlight=group_send#groups

Upvotes: 4

Chiefir
Chiefir

Reputation: 2671

I have thought couple a days about this problem and have an idea how this can be implemented, but can't test it currently. You should try to change your receive() method like this:

async def receive(self, text_data=None, bytes_data=None):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        users_to_kick = text_data_json['kick']

        # you should inspect scope['user'] cuz I am not sure in what place
        # user's id is placed, but there is 'user' object.
        if self.scope['user']['id'] in list(map(int, users_to_kick)):
            await self.close()
        else:
            await self.channel_layer.group_send(
                self.room_group_name,
                {
                    'type': 'some_method',
                    'message': message
                 }
             )

You have to have Authorisation system enabled, you can't kick Anonymous users. And you have to send from Front-End a list of users which you want to kick.

Upvotes: 0

James Foley
James Foley

Reputation: 129

I solved this in the end by storing each channel name (self.channel_name) on channel connection, and removing them on disconnect. These are then tied to a Django user object.

Now, if I want to remove a user from a group, I can just loop over all stored channel names tied to a user object, and run group_discard.

Upvotes: -1

Kyryl Havrylenko
Kyryl Havrylenko

Reputation: 694

You need to prevent connect based on scope['user'] in consumer connect method like this:

class MyConsumer(AsyncJsonWebsocketConsumer):

    async def connect(self):
        id_cannot_connect = 1
        if self.scope['user'] == id_cannot_connect:
            await self.close()
        else:
            await self.accept()

If you want to make lists of users allowed to connect to specific groups you'll need to store groups and group users in your database and use it the same way in connect method like above.

edit: You can discard user's channel from the group with group_discard in receive_json where you still have access to self.scope['user'] to filter needed users.

Upvotes: -1

Related Questions