GitHub user dosubot[bot] added a comment to the discussion: Multi-Tenant User 
management

<!-- Answer -->
You're absolutely right—when FAB_ADD_SECURITY_API is enabled in Superset 5.0.0, 
the /api/v1/security/users/ and /api/v1/security/roles/ endpoints are handled 
directly by Flask AppBuilder's UserApi and RoleApi, not by any 
Superset-specific RoleRestAPI or SupersetRoleApi classes. Superset delegates 
these endpoints to FAB, and there are no wrappers or hooks in the Superset 
codebase for these APIs in this mode 
[reference](https://github.com/apache/superset/blob/829e4d92d91ceae4b43b1ed3b063ffe45377799c/superset/security/manager.py).

To implement tenant-based filtering for the roles dropdown, you need to 
subclass FAB's RoleApi and override its list method. Register your custom 
subclass using appbuilder.add_api inside the FLASK_APP_MUTATOR function in 
superset_config.py (all imports and registration must happen inside this 
function to avoid context errors). Example:

```python
# custom_role_api.py
from flask import g
from flask_appbuilder.security.sqla.apis import RoleApi
from superset.extensions import security_manager

class TenantRoleApi(RoleApi):
    def list(self):
        user_roles = [role.name for role in 
security_manager.get_user_roles(g.user)]
        # Example: restrict to "Tenant-user" if current user is "Tenant-manager"
        if "Tenant-manager" in user_roles:
            self.datamodel.query = 
self.datamodel.query.filter_by(name="Tenant-user")
        return super().list()
```

```python
# superset_config.py
def FLASK_APP_MUTATOR(app):
    from custom_role_api import TenantRoleApi
    appbuilder = app.appbuilder
    # Remove the default RoleApi and register your override for the same 
endpoint
    appbuilder.add_api(TenantRoleApi)
```

This will only affect the /api/v1/security/roles/ endpoint and not disrupt 
other APIs. Keep your override logic in sync with upstream changes to FAB's 
RoleApi for future upgrades.


<!-- Dosu Comment Footer -->
*To reply, just mention [@dosu](https://go.dosu.dev/dosubot).*

---
<sup>How did I do? 
[Good](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=great_response)
 | 
[Irrelevant](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=irrelevant_answer)
 | 
[Incorrect](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=incorrect_sources)
 | 
[Verbose](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=too_verbose)
 | 
[Hallucination](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=hallucination)
 | [Report 
🐛](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=bug_report)
 | 
[Other](https://app.dosu.dev/response-feedback/f6b19a1b-3abc-40fa-a070-4f4f35f76183?feedback_type=other)</sup>&nbsp;&nbsp;[![Join
 
Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Sh
 are on 
X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/apache/superset/discussions/33877)

GitHub link: 
https://github.com/apache/superset/discussions/33877#discussioncomment-13680161

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: 
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to