# Daily Tips - Control Permissions Precisely 🏛

**URL:** <https://community.plotly.com/t/daily-tips-control-permissions-precisely/63515>\
**Category:** Dash Python\
**Tags:** tips-and-tricks\
**Created:** [April 28, 2022, 1:10pm UTC](https://community.plotly.com/t/daily-tips-control-permissions-precisely/63515 "2022-04-28T13:10:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/stu/32/18439_2.png) [@stu](https://community.plotly.com/u/stu)\
**Post date:** [April 28, 2022, 1:10pm UTC](https://community.plotly.com/t/daily-tips-control-permissions-precisely/63515/1 "2022-04-28T13:10:58Z")

</div>

Hi there,

This week I saw someone working on how flask-login could be used in dash. I’m curious if anyone cares about permissions after login.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/3/3/33d60efb25830cc8de47992552de6644139f1025.jpeg)

When dash is used in an organization, we have needs from different users, and their demands may overlap but not the same. If I can meet their needs in the same dashboard, then I can save a lot of time and cost.

There is a framework that helps us do this.

> **[GitHub - osohq/oso: Deprecated: See README](https://github.com/osohq/oso)**
>
> Deprecated: See README

I did some preliminary exploration.  
Here’s the code.

`app.py`

```auto
from doctest import OutputChecker
from dash import Dash, html, dcc, Input, Output
import dash_auth
from oso import Oso, NotFoundError
from models import User, Component
from flask import request

# Initialize the Oso object. This object is usually used globally throughout
# an application.
oso = Oso()

# Tell Oso about the data you will authorize. These types can be referenced
# in the policy.
oso.register_class(User)
oso.register_class(Component)

# Load your policy files.
oso.load_files(["main.polar"])

VALID_USERNAME_PASSWORD_PAIRS = {
    "larry": "abc",
    "anne": "abc",
    "graham": "abc",
    "ivy": "abc",
}

app = Dash( __name__ )

auth = dash_auth.BasicAuth(app, VALID_USERNAME_PASSWORD_PAIRS)

def is_visible(comp, comp_type):
    try:
        oso.authorize(
            User.get_current_user(request.authorization["username"]),
            "visible",
            Component.get(comp_type),
        )
        return comp
    except NotFoundError:
        return html.Div("Unauthorized.")

app.layout = html.Div([html.Div(id="content"), html.Button(id="btn")])

@app.callback(Output("content", "children"), Input("btn", "n_clicks"))
def update(n):
    return [
        is_visible(html.Div("This is for public."), "public"),
        is_visible(html.Div("This is for private."), "private"),
        is_visible(html.Div("This is for admin."), "admin"),
    ]

if __name__ == " __main__":
    app.run_server(debug=True)

```

`model.py`

```auto
from dataclasses import dataclass

from typing import List

@dataclass

class Component:

    name: str

    is_public: bool = False

    @staticmethod

    def get(name):

        return comp_db.get(name)

@dataclass

class Role:

    name: str

    component: Component

@dataclass

class User:

    roles: List[Role]

    @staticmethod

    def get_current_user(name):

        return users_db[name]

comp_db = {

    "public": Component("public", is_public=True),

    "admin": Component("admin"),

    "private": Component("private"),

}

users_db = {

    "larry": User(

        [

            Role(

                name="admin",

                component=comp_db["admin"],

            ),

            Role(

                name="admin",

                component=comp_db["private"],

            ),

        ]

    ),

    "anne": User(

        [

            Role(

                name="maintainer",

                component=comp_db["private"],

            )

        ]

    ),

    "graham": User(

        [

            Role(

                name="contributor",

                component=comp_db["private"],

            )

        ]

    ),

    "ivy": User(

        [

            Role(

                name="visitor",

                component=comp_db["public"],

            ),

        ]

    ),

}

```

`main.polar`

```auto
actor User {}

resource Component {

  permissions = ["visible"];

  roles = ["contributor", "maintainer", "admin", "visitor"];

  "visible" if "visitor";

  "maintainer" if "admin";

  "contributor" if "maintainer";

  "visitor" if "contributor";

}

has_role(actor: User, role_name: String, component:Component) if

  role in actor.roles and

  role_name = role.name and

  role.component = component;

has_permission(_actor: User, "visible", component:Component) if

  component.is_public;

allow(actor, action, resource) if

  has_permission(actor, action, resource);

```

As you can see, they’ve defined a new permission configuration language called polar. However, their documentation mentions that these definitions can also be written in py files.  
like this

```auto
allow(actor, _action, _resource) if actor.username.endswith("example.com");

```

\searrow

```auto
user = User()
user.username = "alice@example.com"
assert(oso.is_allowed(user, "foo", "bar))

```

I’m still figuring it out, and the end result I want to achieve is, for examples, a manager from the Region A can only visit the data for his areas. And there is a drop-down with ten options in total. A table related to other tables in a dashboard is only meaningful to the finance department, and I can only let colleagues in their department see it. A lower rank manager can only see 4 or 5 options, or the drop-down component is disabled for him, but a higher rank manager can see all those options, that is, users see different content based on their role. Or you can give different levels of access to different users based on their position. Then I don’t have to develop redundant dashboards separately for different departments or employees.

* * *

As you may have noticed, I used authorization validation in the callback because the query of userid requires an active HTTP request. In fact, OSO also supports `node.js`, so maybe there could be a dash component can be used to query authorization.

```auto
app.layout = dash_oso.Authorize([html.Div(), html.Div()], "", "")

```

Considering the characteristics of dash, I was thinking that maybe a permission component of dash could be integrated so that it can be used on both the front-end and server-side. It is also possible to implement a decorator for callbacks.

```auto
@dash_oso.authorize(resource="table")
@app.callback(Output(), Input())
def submit():
    db.insert()
    return "success"

```

Implementing these may help Dash be very competitive in authorization feature.

Since I’m not a professional developer, I may have to spend a long time thinking about the feasibility of this stuff. Or if anyone is interested in helping and discussing it would be great.

  
  
  
  
  

Hope you like this. XD

#### Keywords: OSO, RBAC, ABAC, Flask-login, Flask-dance, Data Filtering, SQLAlchemy, Auth

Other Daily Tips series:  
[Daily Tips - If I have a Bunch of Triggers](https://community.plotly.com/t/daily-tips-if-i-have-a-bunch-of-triggers/62881)  
[Daily Tips - Share the Function](https://community.plotly.com/t/daily-tips-share-the-function/63020)  
[Daily Tips - How many Ways to share Dash in a company?](https://community.plotly.com/t/daily-tips-how-many-ways-to-share-dash-in-a-company/62934)  
[Daily Tips - Give your Component a Name](https://community.plotly.com/t/daily-tips-give-your-component-a-name/62864)  
[Daily Tips - Share Dash to Social Media](https://community.plotly.com/t/daily-tips-share-dash-to-social-media/63076)  
[Daily Tips - Double-click to open Dash](https://community.plotly.com/t/daily-tips-double-click-to-open-dash/62962)  
[Daily Tips - What rows of data have I modified?](https://community.plotly.com/t/daily-tips-what-rows-of-data-have-i-modified/62898)  
[Daily Tips - Write the Simplest Client-side Callback](https://community.plotly.com/t/daily-tips-write-the-simplest-client-side-callback/62886)  
[Daily Tips - Some simple Expressions](https://community.plotly.com/t/daily-tips-some-simple-expressions/63062)  
[Daily Tips - IoT? Real Real-time Data and Live Update](https://community.plotly.com/t/daily-tips-iot-real-real-time-data-and-live-update/63106)  
[Daily Tips - Which formatter is your favorite?](https://community.plotly.com/t/daily-tips-which-formatter-is-your-favorite/63154)  
[Daily Tips - Convert a React Component to Dash](https://community.plotly.com/t/daily-tips-convert-a-react-component-to-dash/63352)  
[Daily Tips - Real-time Logs on Dash](https://community.plotly.com/t/daily-tips-real-time-logs-on-dash/63384)

---

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/stu/32/18439_2.png) [@stu](https://community.plotly.com/u/stu)\
**Post date:** [April 30, 2022, 1:49pm UTC](https://community.plotly.com/t/daily-tips-control-permissions-precisely/63515/2 "2022-04-30T13:49:08Z")

</div>

Progress: They are interested in integration. We may soon have a battery-included authorization system for Dash. @dash-beginner

> <https://github.com/osohq/oso/issues/1569>
>
> Hi there,
> 
> I'd like to invite you to take a look at this \[project\](https://git…hub.com/plotly/dash). 
> 
> It's built on top of Flask, but it doesn't have much in common with Flask in use. This is a way to write React in Python. However, it still doesn't have a good permission system. Given the characteristic of Dash, I believe OSO is a rare and awesome authorization system that fits it very well. 
> 
> I only have some preliminary ideas at present, such as there may be a Dash component that integrated OSO to wrap other components for authentication, and there may be a decorator to decorate the Dash callbacks. Also to control the options of the drop-down with data filter. Alternatively, it might be a good idea to use Dash components to develop authorization GUI pages.
> 
> \`\`\`
> app.layout = dash\_oso.Authorize(\[html.Div(), html.Div()\], "", "")
> \`\`\`
> \`\`\`
> @dash\_oso.authorize(resource="table")
> @app.callback(Output(), Input())
> def submit():
> db.insert()
> return "success"
> \`\`\`
> 
> And because of the OSO's feature of multi-language support, my guess that the authorization system could work at the front and back ends at the same time with Dash.
> 
> I think this will probably be an interesting and challenging thing to do. I hope some of you are interested in this, how about we invite a couple of developers from both sides to talk about the feasibility of it? 😋

I hope Dash developers who are interested in this will also actively participate in this discussion. Thanks!

---

<div class="post-metadata">

**Author:** ![dash-beginner](https://avatars.discourse-cdn.com/v4/letter/d/d26b3c/32.png) [@dash-beginner](https://community.plotly.com/u/dash-beginner)\
**Post date:** [May 2, 2022, 3:50pm UTC](https://community.plotly.com/t/daily-tips-control-permissions-precisely/63515/3 "2022-05-02T15:50:34Z")

</div>

Wow that would be incredible!! Great work and please do keep me posted on any updates 🙂 (I’ll try to follow along, but I anticipate that it will quickly get a bit out of my realm of knowledge, hence the moniker on this forum haha).
