Different user access login to different page in dash_auth

You need to have the roles listed as well in the dictionary.

Hmm, I’ll take a look at the code on my computer later.

the roles is listed in the dataframe.

username password role
test test admin
hello world user
user 123 user

What I normally do is this.

users = pd.read_sql(‘select * from tblUsers’, con).index(‘username’).to_dict(‘records’)

If use your method, will not require the VALID_USERNAME_PASSWORD_PAIRS?

normally, i will do like this :

df_userpwd = pd.read_sql_query('''


               SELECT * FROM dbo.DRR_UsernamePwd
                
                          
                 ''', conn)  


VALID_USERNAME_PASSWORD_PAIRS = df_userpwd.set_index('username')['password'].to_dict()

But now have additional one more column to call the role listing, so I not sure how can I add in the VALID_USERNAME_PASSWORD_PAIRS.

Don’t put passwords, otherwise you won’t have the roles.

mean I just remove the password right?

VALID_USERNAME_PASSWORD_PAIRS = df_userpwd.set_index('username').to_dict()

What that should do is this:

{'test':{'password':'test', 'role': 'admin'},
'hello':{'password':'world', 'role':'user'},
'user':{'password':'123','role':'user'}
}

Where the username is the key that determines the information.

how about if all the information is store in dataframe or database?

As long as you convert it in this dictionary, it is easy to reference with the username.

hi @jinnyzor, how about this?

How’s your page-2 look?

my page 2 is hide in the menu bar

Yes, but how is it registered?

dash.register_page(__name__,
                   path='/page2',  # '/' is home page and it represents the url
                   name=' page2',  # name of page, commonly used as name of link
                   title='page2',  # title that appears on browser's tab
                   icon="bi bi-clipboard-check",
                   # image='pg1.png',  # image in the assets folder
                   # description='Histograms are the new bar charts.'
)

require_login(__name__, 
              access_level=['admin', 'user']
              )


Did you take out the .id from current_user?

for all the current_user?

yes, but still hide in menu bar

What does it say if you put it back in again?

for page in dash.page_registry.values():
        if (
            page["name"] not in home
            and page["path"] in restricted_page
            and "access_level" in restricted_page[page["path"]]
        ):
            if VALID_USERNAME_PASSWORD.get(current_user):
            # if VALID_USERNAME_PASSWORD_PAIRS.get(current_user):

                if (
                    VALID_USERNAME_PASSWORD.get(current_user.id)["role"]
                    # VALID_USERNAME_PASSWORD_PAIRS.get(current_user.id)["role"]

                    in restricted_page[page["path"]]["access_level"]
                ):

if VALID_USERNAME_PASSWORD.get(current_user): id in here must remove, if not, will not work.
other current user has put it back, but is same, still hidden

here is the full app.py:

import os
from flask import Flask, request, redirect, session
from flask_login import login_user, LoginManager, UserMixin, logout_user, current_user

import dash
from dash import dcc, html, Input, Output, State, ALL
from dash.exceptions import PreventUpdate
from utils.login_handler import restricted_page


import plotly.express as px
from plotly.offline import plot


import dash_bootstrap_components as dbc
import dash_mantine_components as dmc
from dash_iconify import DashIconify

import pandas as pd
from pprint import pp



# Exposing the Flask Server to enable configuring it for logging in
server = Flask(__name__)


@server.route('/login', methods=['POST'])
def login_button_click():
    if request.form:
        username = request.form['username']
        password = request.form['password']
        
        if VALID_USERNAME_PASSWORD.get(username) is None:
        # if VALID_USERNAME_PASSWORD_PAIRS.get(username) is None:
   
            return """invalid username and/or password <a href='/login'>login here</a>"""
        
        if VALID_USERNAME_PASSWORD.get(username)['password'] == password:
        # if VALID_USERNAME_PASSWORD_PAIRS.get(username)['password'] == password:

            login_user(User(username))
            if 'url' in session:
                if session['url']:
                    url = session['url']
                    session['url'] = None
                    return redirect(url) ## redirect to target url
            return redirect('/') ## redirect to home
        return """invalid username and/or password <a href='/login'>login here</a>"""


app = dash.Dash(
    __name__, server=server, use_pages=True, suppress_callback_exceptions=True
    ,external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.BOOTSTRAP],
                meta_tags=[{'name': 'viewport',
                            'content': 'width=device-width, initial-scale=1.0'}]
)

# auth = dash_auth.BasicAuth(app, VALID_USERNAME_PASSWORD_PAIRS)

# Keep this out of source code repository - save in a file or a database
#  passwords should be encrypted
# VALID_USERNAME_PASSWORD = {"abc": "abc", "welcome": "world"}

VALID_USERNAME_PASSWORD = {"abc": {"password":"abc", "role":"admin"}, "hello": {"password":"world", "role":"user"}}

# df_userpwd= pd.read_csv("pwd.csv")

# df_userpwd= pd.read_csv("pwd.csv").set_index('username').transpose()

# userpwd = pp(df_userpwd.to_dict())
# VALID_USERNAME_PASSWORD = pp(df_userpwd.to_dict())

# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
server.config.update(SECRET_KEY='291a47103f3cd8fc26d05ffc7b31e33f73ca3d459d6259bd')

# Login manager object will be used to login / logout users
login_manager = LoginManager()
login_manager.init_app(server)
login_manager.login_view = "/login"


class User(UserMixin):
    # User data model. It has to have at least self.id as a minimum
    def __init__(self, username):
        self.id = username


@login_manager.user_loader
def load_user(username):
    """This function loads the user by user id. Typically this looks up the user from a user database.
    We won't be registering or looking up users in this example, since we'll just login using LDAP server.
    So we'll simply return a User object with the passed in username.
    """
    return User(username)


SIDEBAR_STYLE = {
    "position": "fixed",
    "width": "20rem",
    "padding": "2rem 1rem",
    "background-color": "#cbd3dd",
    "z-index": 1050,
    "transition": "width 0.1s ease-in-out",
}

# padding for the page content
CONTENT_STYLE = {
    "margin-left": "10rem",
    "margin-right": "2rem",
    "padding": "2rem 1rem",

}

content = html.Div(id="page-content", children=[], 
                    style=CONTENT_STYLE
                    )


home = [' Home', ' About', ' login', ' Logout', ' Permission']

    
######################    
# sidebar = dbc.Nav([

#     dbc.NavLink([
#         html.Div([
#             html.I(className='bi bi-house', style={'position': 'absolute', 'left': '42px'}),
#             html.Span(' Home', style={'padding-left': '20px'}),
#         ], className="ms-2"),
#     ],
#         href='/',
#         active="exact",
#     ),

#     dmc.Accordion(
#         dmc.AccordionItem([
#             dbc.NavLink([
#                 html.Div([
#                     html.I(className=page["icon"]),
#                     page["name"]
#                 ], className="ms-2"),
#             ],
#                 href=page["path"],
#                 active="exact",
#             )
#             for page in dash.page_registry.values() if page['name'] not in home

#         ], label='Profile',
#             icon=[
#                 DashIconify(
#                     icon="carbon:search-locate",
#                     color=dmc.theme.DEFAULT_COLORS["blue"][6],
#                     width=20,
#                 )
#             ],

#         ),

#         multiple=True,
#         disableIconRotation=True,
#     ),
    
#     dbc.NavLink([
#         html.Div([
#             html.I(className='bi bi-box-arrow-right', style={'position': 'absolute', 'left': '42px'}),
#             html.Span(' Logout', style={'padding-left': '20px'}),
#         ], className="ms-2"),
#     ],
#         href='/logout',
#         active="exact",
#     ),
    
    
# ],
#     vertical=True,
#     pills=True,
    
#     # className="bg-light",
#     # className="sidebar"
# )
########################

def navigation():
    navs = []
    for page in dash.page_registry.values():
        if page["name"] not in home and page["path"] not in restricted_page:
            navs.append(
                dbc.NavLink(
                    [
                        html.Div(
                            [html.I(className=page["icon"]), page["name"]],
                            className="ms-2",
                        ),
                    ],
                    href=page["path"],
                    active="exact",
                )
            )

    for page in dash.page_registry.values():
        if (
            page["name"] not in home
            and page["path"] in restricted_page
            and "access_level" not in restricted_page[page["path"]]
        ):
            navs.append(
                dbc.NavLink(
                    [
                        html.Div(
                            [html.I(className=page["icon"]), page["name"]],
                            className="ms-2",
                        ),
                    ],
                    href=page["path"],
                    active="exact",
                )
            )

    for page in dash.page_registry.values():
        if (
            page["name"] not in home
            and page["path"] in restricted_page
            and "access_level" in restricted_page[page["path"]]
        ):
            if VALID_USERNAME_PASSWORD.get(current_user):
            # if VALID_USERNAME_PASSWORD_PAIRS.get(current_user):

                if (
                    VALID_USERNAME_PASSWORD.get(current_user.id)["role"]
                    # VALID_USERNAME_PASSWORD_PAIRS.get(current_user.id)["role"]

                    in restricted_page[page["path"]]["access_level"]
                ):
                    navs.append(
                        dbc.NavLink(
                            [
                                html.Div(
                                    [html.I(className=page["icon"]), page["name"]],
                                    className="ms-2",
                                ),
                            ],
                            href=page["path"],
                            active="exact",
                        )
                    )

    return navs


# page 1 data
def sidebar():
    sidebar = dbc.Nav(
        [
            dbc.NavLink(
                [
                    html.Div(
                        [
                            html.I(
                                className="bi bi-house",
                                style={"position": "absolute", "left": "42px"},
                            ),
                            html.Span(" Home", style={"padding-left": "20px"}),
                        ],
                        className="ms-2",
                    ),
                ],
                href="/",
                active="exact",
            ),
            dmc.Accordion(
                dmc.AccordionItem(
                    navigation(),
                    label="Profile",
                    icon=[
                        DashIconify(
                            icon="carbon:search-locate",
                            color=dmc.theme.DEFAULT_COLORS["blue"][6],
                            width=20,
                        )
                    ],
                ),
                multiple=True,
                disableIconRotation=True,
            ),
            dbc.NavLink(
                [
                    html.Div(
                        [
                            html.I(
                                className="bi bi-box-arrow-right",
                                style={"position": "absolute", "left": "42px"},
                            ),
                            html.Span(" Logout", style={"padding-left": "20px"}),
                        ],
                        className="ms-2",
                    ),
                ],
                href="/logout",
                active="exact",
            ),
        ],
        vertical=True,
        pills=True,
        # className="bg-light",
        # className="sidebar"
    )
    return sidebar

########################

app.layout = dbc.Container([
    dcc.Location(id="url"),
         
        
    html.Div([
        dbc.Button(html.I(className ="bi bi-list"), #"Menu",
             id="open-offcanvas", n_clicks=0),
        
        dbc.Offcanvas([

              sidebar(),
              content
              ],
           
            id="offcanvas",
          title="Welcome to .../",
          is_open=False,
          scrollable = True,
          backdrop="static",
          style=SIDEBAR_STYLE,
           # className="sidebar-header"
              ),
        ],
        style={'position': 'fixed'}, 
        
        ),   
    
    # html.Div([
    #     dbc.Nav([
    #         dbc.NavLink(id = 'home', href="/", className='bi bi-house'),
    #         dbc.NavLink(id = 'logout', href="/logout", className='bi bi-box-arrow-right'),
    #         ], id = 'nav'
    #         , className="d-grid gap-2 d-md-flex justify-content-md-end"
        
    #         ),
    #     ]),
    
    html.Div(id="user-status-header"),

    dbc.Row([
            # dbc.Col(
            #     [html.Div([
            #         sidebar
            #         ]),
            #     ], xs=4, sm=4, md=2, lg=2, xl=2, xxl=2),

            # dbc.Col([
                    dash.page_container
                # ], xs=8, sm=8, md=10, lg=10, xl=10, xxl=10)
        ], className="content"
    )


    ], fluid=True)
    # return layout



@app.callback(
    Output("offcanvas", "is_open"),
    Input("open-offcanvas", "n_clicks"),
    [State("offcanvas", "is_open")],
)
def toggle_offcanvas(n1, is_open):
    if n1:
        return not is_open
    return is_open



@app.callback(
    Output("user-status-header", "children"),
    Output('url','pathname'),
    Output('open-offcanvas','style'),
    # Output('nav','style'),
    Input("url", "pathname"),
    Input({'index': ALL, 'type':'redirect'}, 'n_intervals')
)


def update_authentication_status(path, n):
    ### logout redirect
    if n:
        if not n[0]:
            return '', dash.no_update, {'display':'none'}
        else:
            return '', '/login', {'display':'none'}


    ### test if user is logged in
    if current_user.is_authenticated:
        if path in restricted_page:
              if 'access_level' in restricted_page[path]:
                  if (VALID_USERNAME_PASSWORD[current_user.id]['role'] not in restricted_page[path]['access_level']):
                  # if (VALID_USERNAME_PASSWORD_PAIRS[current_user.id]['role'] not in restricted_page[path]['access_level']):
   
                      return (dcc.Link("",id = 'logout', href="/logout", style={'position': 'fixed'})), '/permission', {'display':'initial'}
        
        
        if path == '/login':
            return (dcc.Link("" , id = 'logout', href="/logout", style={'position': 'fixed'}), '/', {'display':'initial'})
        return (dcc.Link("",id = 'logout', href="/logout", style={'position': 'fixed'}), dash.no_update, {'display':'initial'})
    
    
    else:
        ### if page is restricted, redirect to login and save path
        if path in restricted_page:
            session['url'] = path
            return dcc.Link("login", href="/login"), '/login', {'display':'none'}


    ### if path not login and logout display login link
    if current_user and path not in ['/login', '/logout']:
        return dcc.Link("login", href="/login"), dash.no_update, {'display':'initial'}

    ### if path login and logout hide links
    if path in ['/login', '/logout']:
        return '', dash.no_update, {'display':'none'}

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

# app.run(debug=True, port='1009')

##################################

# @app.route('/login', methods=['GET', 'POST'])
# def login():
#     error = None
#     if request.method == 'POST':
#         if request.form['username'] != 'admin' or request.form['password'] != 'admin':
#             error = 'Invalid Credentials. Please try again.'
#         else:
#             return redirect(url_for('home'))
#     return render_template('login.html', error=error)

Alright, here you go:

import os
from flask import Flask, request, redirect, session
from flask_login import login_user, LoginManager, UserMixin, logout_user, current_user

import dash
from dash import dcc, html, Input, Output, State, ALL
from dash.exceptions import PreventUpdate
from utils.login_handler import restricted_page

import plotly.express as px
from plotly.offline import plot

import dash_bootstrap_components as dbc
import dash_mantine_components as dmc
from dash_iconify import DashIconify

import pandas as pd
from pprint import pp

# Exposing the Flask Server to enable configuring it for logging in
server = Flask(__name__)


@server.route('/login', methods=['POST'])
def login_button_click():
    if request.form:
        username = request.form['username']
        password = request.form['password']

        if VALID_USERNAME_PASSWORD.get(username) is None:
            # if VALID_USERNAME_PASSWORD_PAIRS.get(username) is None:

            return """invalid username and/or password <a href='/login'>login here</a>"""

        if VALID_USERNAME_PASSWORD.get(username)['password'] == password:
            # if VALID_USERNAME_PASSWORD_PAIRS.get(username)['password'] == password:

            login_user(User(username))
            if 'url' in session:
                if session['url']:
                    url = session['url']
                    session['url'] = None
                    return redirect(url)  ## redirect to target url
            return redirect('/')  ## redirect to home
        return """invalid username and/or password <a href='/login'>login here</a>"""


app = dash.Dash(
    __name__, server=server, use_pages=True, suppress_callback_exceptions=True
    , external_stylesheets=[dbc.themes.BOOTSTRAP, dbc.icons.BOOTSTRAP],
    meta_tags=[{'name': 'viewport',
                'content': 'width=device-width, initial-scale=1.0'}]
)

# auth = dash_auth.BasicAuth(app, VALID_USERNAME_PASSWORD_PAIRS)

# Keep this out of source code repository - save in a file or a database
#  passwords should be encrypted
# VALID_USERNAME_PASSWORD = {"abc": "abc", "welcome": "world"}

VALID_USERNAME_PASSWORD = {"abc": {"password": "abc", "role": "admin"}, "hello": {"password": "world", "role": "user"}}

# df_userpwd= pd.read_csv("pwd.csv")

# df_userpwd= pd.read_csv("pwd.csv").set_index('username').transpose()

# userpwd = pp(df_userpwd.to_dict())
# VALID_USERNAME_PASSWORD = pp(df_userpwd.to_dict())

# Updating the Flask Server configuration with Secret Key to encrypt the user session cookie
server.config.update(SECRET_KEY='291a47103f3cd8fc26d05ffc7b31e33f73ca3d459d6259bd')

# Login manager object will be used to login / logout users
login_manager = LoginManager()
login_manager.init_app(server)
login_manager.login_view = "/login"


class User(UserMixin):
    # User data model. It has to have at least self.id as a minimum
    def __init__(self, username):
        self.id = username


@login_manager.user_loader
def load_user(username):
    """This function loads the user by user id. Typically this looks up the user from a user database.
    We won't be registering or looking up users in this example, since we'll just login using LDAP server.
    So we'll simply return a User object with the passed in username.
    """
    return User(username)


SIDEBAR_STYLE = {
    "position": "fixed",
    "width": "20rem",
    "padding": "2rem 1rem",
    "background-color": "#cbd3dd",
    "z-index": 1050,
    "transition": "width 0.1s ease-in-out",
}

# padding for the page content
CONTENT_STYLE = {
    "margin-left": "10rem",
    "margin-right": "2rem",
    "padding": "2rem 1rem",

}

content = html.Div(id="page-content", children=[],
                   style=CONTENT_STYLE
                   )

home = [' Home', ' About', ' login', ' Logout', ' Permission']


######################
# sidebar = dbc.Nav([

#     dbc.NavLink([
#         html.Div([
#             html.I(className='bi bi-house', style={'position': 'absolute', 'left': '42px'}),
#             html.Span(' Home', style={'padding-left': '20px'}),
#         ], className="ms-2"),
#     ],
#         href='/',
#         active="exact",
#     ),

#     dmc.Accordion(
#         dmc.AccordionItem([
#             dbc.NavLink([
#                 html.Div([
#                     html.I(className=page["icon"]),
#                     page["name"]
#                 ], className="ms-2"),
#             ],
#                 href=page["path"],
#                 active="exact",
#             )
#             for page in dash.page_registry.values() if page['name'] not in home

#         ], label='Profile',
#             icon=[
#                 DashIconify(
#                     icon="carbon:search-locate",
#                     color=dmc.theme.DEFAULT_COLORS["blue"][6],
#                     width=20,
#                 )
#             ],

#         ),

#         multiple=True,
#         disableIconRotation=True,
#     ),

#     dbc.NavLink([
#         html.Div([
#             html.I(className='bi bi-box-arrow-right', style={'position': 'absolute', 'left': '42px'}),
#             html.Span(' Logout', style={'padding-left': '20px'}),
#         ], className="ms-2"),
#     ],
#         href='/logout',
#         active="exact",
#     ),


# ],
#     vertical=True,
#     pills=True,

#     # className="bg-light",
#     # className="sidebar"
# )
########################

def navigation():
    navs = []
    for page in dash.page_registry.values():
        if page["name"] not in home and page["path"] not in restricted_page:
            navs.append(
                dbc.NavLink(
                    [
                        html.Div(
                            [#html.I(className=page["icon"]),
                             page["name"]],
                            className="ms-2",
                        ),
                    ],
                    href=page["path"],
                    active="exact",
                )
            )

    for page in dash.page_registry.values():
        if (
                page["name"] not in home
                and page["path"] in restricted_page
                and "access_level" not in restricted_page[page["path"]]
        ):
            navs.append(
                dbc.NavLink(
                    [
                        html.Div(
                            [#html.I(className=page["icon"]),
                            page["name"]],
                            className="ms-2",
                        ),
                    ],
                    href=page["path"],
                    active="exact",
                )
            )

    for page in dash.page_registry.values():
        if (
                page["name"] not in home
                and page["path"] in restricted_page
                and "access_level" in restricted_page[page["path"]]
        ):
            if current_user:
                # if VALID_USERNAME_PASSWORD_PAIRS.get(current_user):
                if (
                        VALID_USERNAME_PASSWORD[current_user.id]["role"]
                        # VALID_USERNAME_PASSWORD_PAIRS.get(current_user.id)["role"]

                        in restricted_page[page["path"]]["access_level"]
                ):
                    navs.append(
                        dbc.NavLink(
                            [
                                html.Div(
                                    [#html.I(className=page["icon"]),
                                     page["name"]],
                                    className="ms-2",
                                ),
                            ],
                            href=page["path"],
                            active="exact",
                        )
                    )

    return navs


# page 1 data
def sidebar():
    sidebar = dbc.Nav(
        [
            dbc.NavLink(
                [
                    html.Div(
                        [
                            html.I(
                                className="bi bi-house",
                                style={"position": "absolute", "left": "42px"},
                            ),
                            html.Span(" Home", style={"padding-left": "20px"}),
                        ],
                        className="ms-2",
                    ),
                ],
                href="/",
                active="exact",
            ),
            dmc.Accordion(
                dmc.AccordionItem(
                    navigation(),
                    label="Profile",
                    icon=[
                        DashIconify(
                            icon="carbon:search-locate",
                            color=dmc.theme.DEFAULT_COLORS["blue"][6],
                            width=20,
                        )
                    ],
                ),
                multiple=True,
                disableIconRotation=True,
            ),
            dbc.NavLink(
                [
                    html.Div(
                        [
                            html.I(
                                className="bi bi-box-arrow-right",
                                style={"position": "absolute", "left": "42px"},
                            ),
                            html.Span(" Logout", style={"padding-left": "20px"}),
                        ],
                        className="ms-2",
                    ),
                ],
                href="/logout",
                active="exact",
            ),
        ],
        vertical=True,
        pills=True,
        # className="bg-light",
        # className="sidebar"
    )
    return sidebar


########################

app.layout = dbc.Container([
    dcc.Location(id="url"),

    html.Div([
        dbc.Button(html.I(className="bi bi-list"),  # "Menu",
                   id="open-offcanvas", n_clicks=0),

        dbc.Offcanvas([

            sidebar(),
            content
        ],

            id="offcanvas",
            title="Welcome to .../",
            is_open=False,
            scrollable=True,
            backdrop="static",
            style=SIDEBAR_STYLE,
            # className="sidebar-header"
        ),
    ],
        style={'position': 'fixed'},

    ),

    # html.Div([
    #     dbc.Nav([
    #         dbc.NavLink(id = 'home', href="/", className='bi bi-house'),
    #         dbc.NavLink(id = 'logout', href="/logout", className='bi bi-box-arrow-right'),
    #         ], id = 'nav'
    #         , className="d-grid gap-2 d-md-flex justify-content-md-end"

    #         ),
    #     ]),

    html.Div(id="user-status-header"),

    dbc.Row([
        # dbc.Col(
        #     [html.Div([
        #         sidebar
        #         ]),
        #     ], xs=4, sm=4, md=2, lg=2, xl=2, xxl=2),

        # dbc.Col([
        dash.page_container
        # ], xs=8, sm=8, md=10, lg=10, xl=10, xxl=10)
    ], className="content"
    )

], fluid=True)


# return layout


@app.callback(
    Output("offcanvas", "is_open"),
    Output("offcanvas","children"),
    Input("open-offcanvas", "n_clicks"),
    [State("offcanvas", "is_open")],
)
def toggle_offcanvas(n1, is_open):
    if n1:
        return not is_open, [sidebar(), content]
    return is_open, dash.no_update


@app.callback(
    Output("user-status-header", "children"),
    Output('url', 'pathname'),
    Output('open-offcanvas', 'style'),
    # Output('nav','style'),
    Input("url", "pathname"),
    Input({'index': ALL, 'type': 'redirect'}, 'n_intervals')
)
def update_authentication_status(path, n):
    ### logout redirect
    if n:
        if not n[0]:
            return '', dash.no_update, {'display': 'none'}
        else:
            return '', '/login', {'display': 'none'}

    ### test if user is logged in
    if current_user.is_authenticated:
        if path in restricted_page:
            if 'access_level' in restricted_page[path]:
                if (VALID_USERNAME_PASSWORD[current_user.id]['role'] not in restricted_page[path]['access_level']):
                    # if (VALID_USERNAME_PASSWORD_PAIRS[current_user.id]['role'] not in restricted_page[path]['access_level']):

                    return (dcc.Link("", id='logout', href="/logout", style={'position': 'fixed'})), '/permission', {
                        'display': 'initial'}

        if path == '/login':
            return (dcc.Link("", id='logout', href="/logout", style={'position': 'fixed'}), '/', {'display': 'initial'})
        return (
        dcc.Link("", id='logout', href="/logout", style={'position': 'fixed'}), dash.no_update, {'display': 'initial'})


    else:
        ### if page is restricted, redirect to login and save path
        if path in restricted_page:
            session['url'] = path
            return dcc.Link("login", href="/login"), '/login', {'display': 'none'}

    ### if path not login and logout display login link
    if current_user and path not in ['/login', '/logout']:
        return dcc.Link("login", href="/login"), dash.no_update, {'display': 'initial'}

    ### if path login and logout hide links
    if path in ['/login', '/logout']:
        return '', dash.no_update, {'display': 'none'}


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

# app.run(debug=True, port='1009')

##################################

# @app.route('/login', methods=['GET', 'POST'])
# def login():
#     error = None
#     if request.method == 'POST':
#         if request.form['username'] != 'admin' or request.form['password'] != 'admin':
#             error = 'Invalid Credentials. Please try again.'
#         else:
#             return redirect(url_for('home'))
#     return render_template('login.html', error=error)