[GH-ISSUE #17308] feat: in __user__ include the list of groups the user is part of #56899

Closed
opened 2026-05-05 20:12:54 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @AlexZorzi on GitHub (Sep 9, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/17308

Check Existing Issues

  • I have searched the existing issues and discussions.

Problem Description

Im managing a openwebui for my company, i was request to track spending by each department, at this time im able to inject in the request headers with only the user ID through the __user__ variable.
To keep things more anonymized i would like to track only the total department usage, since im using Oauth users get synced with their own Group from the identity manager so the data is already there, its just missing from the __user__ variable when making a function.

Desired Solution you'd like

__user__ should contain a list of the user groups, since the user can be part of more than one group

Alternatives Considered

No response

Additional Context

Code i currently use to inject the user id in the request headers

from pydantic import BaseModel, Field
from typing import Optional


class Filter:
    class Valves(BaseModel):
        enable_tracking: bool = Field(
            default=True, description="Enable user tracking for OpenRouter"
        )

    def __init__(self):
        self.valves = self.Valves()

    def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
        if not self.valves.enable_tracking:
            return body

        # Use actual user info if available, otherwise use fallback
        
        user_id = f"openwebui_{__user__['id']}"
        

        # Add user parameter for OpenRouter tracking
        body["user"] = user_id
        print(f"OpenRouter tracking - User: {user_id}")
        return body
Originally created by @AlexZorzi on GitHub (Sep 9, 2025). Original GitHub issue: https://github.com/open-webui/open-webui/issues/17308 ### Check Existing Issues - [x] I have searched the existing issues and discussions. ### Problem Description Im managing a openwebui for my company, i was request to track spending by each department, at this time im able to inject in the request headers with only the user ID through the `__user__` variable. To keep things more anonymized i would like to track only the total department usage, since im using Oauth users get synced with their own Group from the identity manager so the data is already there, its just missing from the `__user__` variable when making a function. ### Desired Solution you'd like `__user__` should contain a list of the user groups, since the user can be part of more than one group ### Alternatives Considered _No response_ ### Additional Context Code i currently use to inject the user id in the request headers ``` from pydantic import BaseModel, Field from typing import Optional class Filter: class Valves(BaseModel): enable_tracking: bool = Field( default=True, description="Enable user tracking for OpenRouter" ) def __init__(self): self.valves = self.Valves() def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict: if not self.valves.enable_tracking: return body # Use actual user info if available, otherwise use fallback user_id = f"openwebui_{__user__['id']}" # Add user parameter for OpenRouter tracking body["user"] = user_id print(f"OpenRouter tracking - User: {user_id}") return body ```
Author
Owner

@hemzet commented on GitHub (Sep 19, 2025):

@AlexZorzi
Workaround:

from open_webui.models.groups import Groups
class Pipe:

        async def pipe(
                self,
                body: dict,
                messages: dict | None = None,
                __user__: Optional[dict] = None,
                **kwargs,
        ) -> tuple:

                user_id = (__user__ or {}).get(“id”)
                if not user_id:
                    return {"groups": [], "note": "No user in context”}

                # Member-of groups
                member_groups = Groups.get_groups_by_member_id(user_id)

                print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")
<!-- gh-comment-id:3312085044 --> @hemzet commented on GitHub (Sep 19, 2025): @AlexZorzi Workaround: ``` from open_webui.models.groups import Groups class Pipe: async def pipe( self, body: dict, messages: dict | None = None, __user__: Optional[dict] = None, **kwargs, ) -> tuple: user_id = (__user__ or {}).get(“id”) if not user_id: return {"groups": [], "note": "No user in context”} # Member-of groups member_groups = Groups.get_groups_by_member_id(user_id) print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}") ```
Author
Owner

@Schnubl commented on GitHub (Sep 28, 2025):

Hi @hemzet , can you pls explain how to use this code and where to put it in, i have also done a workaround for bring groups to frontend and modifyed the core which i dont like because its a pain when new updates released.

Would it be possible to make this a function or a pipe so you dont have to change the core directly?

<!-- gh-comment-id:3342391314 --> @Schnubl commented on GitHub (Sep 28, 2025): Hi @hemzet , can you pls explain how to use this code and where to put it in, i have also done a workaround for bring groups to frontend and modifyed the core which i dont like because its a pain when new updates released. Would it be possible to make this a function or a pipe so you dont have to change the core directly?
Author
Owner

@hemzet commented on GitHub (Sep 28, 2025):

@Schnubl
The snippet shows usage in a pipe function. No modification of core required. Just import the group model and use it.

<!-- gh-comment-id:3343865910 --> @hemzet commented on GitHub (Sep 28, 2025): @Schnubl The snippet shows usage in a pipe function. No modification of core required. Just import the group model and use it.
Author
Owner

@Schnubl commented on GitHub (Sep 29, 2025):

thx for the fast response.
i tried to creat a new function pipe and paste the code into it.
When try to svae it i get an error = "id"

here is the code that i pasted into the new function:

"""
title: Bring Usergroup to Frontend
author: hezmet
author_url: https://github.com/hemzet
version: 0.1
"""

from open_webui.models.groups import Groups
class Pipe:

        async def pipe(
                self,
                body: dict,
                messages: dict | None = None,
                __user__: Optional[dict] = None,
                **kwargs,
        ) -> tuple:

                user_id = (__user__ or {}).get(“id”)
                if not user_id:
                    return {"groups": [], "note": "No user in context”}

                # Member-of groups
                member_groups = Groups.get_groups_by_member_id(user_id)

                print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")

Did i misunderstand you?

<!-- gh-comment-id:3347774597 --> @Schnubl commented on GitHub (Sep 29, 2025): thx for the fast response. i tried to creat a new function pipe and paste the code into it. When try to svae it i get an error = "id" here is the code that i pasted into the new function: ``` """ title: Bring Usergroup to Frontend author: hezmet author_url: https://github.com/hemzet version: 0.1 """ from open_webui.models.groups import Groups class Pipe: async def pipe( self, body: dict, messages: dict | None = None, __user__: Optional[dict] = None, **kwargs, ) -> tuple: user_id = (__user__ or {}).get(“id”) if not user_id: return {"groups": [], "note": "No user in context”} # Member-of groups member_groups = Groups.get_groups_by_member_id(user_id) print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}") ``` Did i misunderstand you?
Author
Owner

@hemzet commented on GitHub (Sep 30, 2025):

Well, the provided code was simply a snippet to showcase the lines you need to add to your function for accessing group data. It's not the full code of a working function.

<!-- gh-comment-id:3350707168 --> @hemzet commented on GitHub (Sep 30, 2025): Well, the provided code was simply a snippet to showcase the lines you need to add to your function for accessing group data. It's not the full code of a working function.
Author
Owner

@AlexZorzi commented on GitHub (Sep 30, 2025):

Thanks @hemzet for the workaround

@Schnubl edit my Function to your needs, i provide a list of groups to track since my users have multiple groups and you can only send one to openrouter.

"""
title: OpenRouter User Tracking Filter
author: AlexZorzi
description: Automatically adds user parameter to API requests for OpenRouter usage tracking
version: 1.0
"""

from pydantic import BaseModel, Field
from typing import Optional, List
from open_webui.models.groups import Groups


class Filter:
    class Valves(BaseModel):
        enable_tracking: bool = Field(
            default=True, description="Enable user tracking for OpenRouter"
        )
        trackable_groups: List[str] = Field(
            default=[
                "Backoffice",
                "WEB",
                "EDP",
                "Fewo",
                "Marketing",
                "HR",
            ],
            description="List of groups to track for department spending",
        )

    def __init__(self):
        self.valves = self.Valves()

    def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
        if not self.valves.enable_tracking:
            return body

        user_id = __user__.get("id") if __user__ else None
        user_email = __user__.get("email") if __user__ else None

        if not user_id:
            print("No user ID available for tracking")
            return body

        # Get user groups
        try:
            member_groups = Groups.get_groups_by_member_id(user_id)
            group_names = [g.name for g in member_groups]
            print(f"User {user_id} is member of groups: {group_names}")
        except Exception as e:
            print(f"Error getting user groups: {e}")
            group_names = []

        # Find trackable group
        trackable_group = None
        for group_name in group_names:
            if group_name in self.valves.trackable_groups:
                trackable_group = group_name
                break

        # Create tracking identifier
        if trackable_group:
            user_tracking_id = f"{trackable_group}"
            print(f"Tracking by department: {trackable_group}")
        else:
            # Fallback to user email if no trackable group found
            user_tracking_id = f"{user_email}" if user_email else f"{user_id}"
            print(
                f"No trackable group found, using user identifier: {user_email or user_id}"
            )

        # Add user parameter for OpenRouter tracking
        body["user"] = user_tracking_id
        print(f"OpenRouter tracking - User: {user_tracking_id}")

        return body

<!-- gh-comment-id:3350844214 --> @AlexZorzi commented on GitHub (Sep 30, 2025): Thanks @hemzet for the workaround @Schnubl edit my Function to your needs, i provide a list of groups to track since my users have multiple groups and you can only send one to openrouter. ``` """ title: OpenRouter User Tracking Filter author: AlexZorzi description: Automatically adds user parameter to API requests for OpenRouter usage tracking version: 1.0 """ from pydantic import BaseModel, Field from typing import Optional, List from open_webui.models.groups import Groups class Filter: class Valves(BaseModel): enable_tracking: bool = Field( default=True, description="Enable user tracking for OpenRouter" ) trackable_groups: List[str] = Field( default=[ "Backoffice", "WEB", "EDP", "Fewo", "Marketing", "HR", ], description="List of groups to track for department spending", ) def __init__(self): self.valves = self.Valves() def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict: if not self.valves.enable_tracking: return body user_id = __user__.get("id") if __user__ else None user_email = __user__.get("email") if __user__ else None if not user_id: print("No user ID available for tracking") return body # Get user groups try: member_groups = Groups.get_groups_by_member_id(user_id) group_names = [g.name for g in member_groups] print(f"User {user_id} is member of groups: {group_names}") except Exception as e: print(f"Error getting user groups: {e}") group_names = [] # Find trackable group trackable_group = None for group_name in group_names: if group_name in self.valves.trackable_groups: trackable_group = group_name break # Create tracking identifier if trackable_group: user_tracking_id = f"{trackable_group}" print(f"Tracking by department: {trackable_group}") else: # Fallback to user email if no trackable group found user_tracking_id = f"{user_email}" if user_email else f"{user_id}" print( f"No trackable group found, using user identifier: {user_email or user_id}" ) # Add user parameter for OpenRouter tracking body["user"] = user_tracking_id print(f"OpenRouter tracking - User: {user_tracking_id}") return body ```
Author
Owner

@seppel123 commented on GitHub (Oct 2, 2025):

Im sorry i really misunderstood that.

I asked to bring the groups into the frontend, this function works in backend und send results to frontend.

<!-- gh-comment-id:3360730597 --> @seppel123 commented on GitHub (Oct 2, 2025): Im sorry i really misunderstood that. I asked to bring the groups into the frontend, this function works in backend und send results to frontend.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#56899