Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

permission disables the option to add routes to customRoutes in app.js #6015

Closed
DanielSanchez94 opened this issue Mar 8, 2021 · 16 comments
Closed

Comments

@DanielSanchez94
Copy link

DanielSanchez94 commented Mar 8, 2021

#5036 and #4821 are the same problem.

It turns out that I want to have the routes created in customRoutes without authentication, but when I add the permissions to the pages with authentication, the pages without authentication are automatically redirected to the login, without showing me any of the customRoutes pages.

I tried returning some resource outside the permissions and it works, so the error is there, you have to return something without necessarily permissions, otherwise it is redirected immediately to the login. Any idea how to keep the permissions and routes scheme in customRoutes without authentication (as I show in my code) and that I can access the routes declared in customRoutes?

import React from 'react';
import { Admin, Resource } from 'react-admin';
import adapterDataProvider from './auth/adapterDataProvider';
import i18nProvider from './i18n/es';
import categories from './categories';
import sellers from './sellers';
import MyLayout from './globalTheme/MyLayout';
import MyTheme from './globalTheme/MyTheme';
import authProvider from "./auth/authProvider";
import MyLogin from './login/MyLogin';
import { Route } from 'react-router-dom';
import SignUpForm from './login/SignUpForm';
import ForgotPasswordForm from './login/ForgotPasswordForm';
import NotFound from './globalTheme/NotFound';
import ResetPasswordForm from './login/ResetPasswordForm';
import ShopIcon from '@material-ui/icons/Shop';
import ProductCreate from './products/create';
import ProductEdit from './products/edit';
import { ProductList } from './products/products';

const App = ( ) => (
        <div> 
            <Admin 
                title="Simple Comercio"
                theme={ MyTheme } 
                disableTelemetry
                catchAll={ NotFound }
                authProvider= { authProvider }
                i18nProvider={ i18nProvider }
                layout={ MyLayout } 
                dataProvider={ adapterDataProvider } 
                loginPage={ MyLogin } 
                customRoutes={[
                    <Route
                        exact
                        path="/signup"
                        component={(props) => <SignUpForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/forgot-password"
                        component={(props) => <ForgotPasswordForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/reset-password"
                        component={(props) => <ResetPasswordForm {...props} />}
                        noLayout
                    />,
                ]}
                >
                { permissions => [
                    permissions.hasOwnProperty('admin') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />,
                        <Resource {...sellers} />]
                    :null,
                    permissions.hasOwnProperty('seller') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />]
                    :null,
                    ]
                }
            </Admin>
        </div>
)
export default App;
``` 
@fzaninotto
Copy link
Member

Hi, and thanks for your input.

I can't reproduce the problem on the simple example: I can access the '/custom' route even when logged out.

We'll need more details to investigate this issue. That's why we've written an issue template listing the elements we need to qualify a bug.

<!-- Please do not submit support requests or "How to" questions here. For that, 
- go to Stack Overflow: https://stackoverflow.com/questions/tagged/react-admin) for community support,  or
- use the Professional Support (https://marmelab.com/ra-enterprise/#support) if you're an Enterprise Edition subscriber. -->

**What you were expecting:**
<!-- Describe what the behavior would be without the bug. -->

**What happened instead:**
<!-- Describe how the bug manifests. -->

**Steps to reproduce:**
<!--  Please explain the steps required to duplicate the issue, especially if you are able to provide a sample application. -->

**Related code:**
<!-- If you are able to illustrate the bug or feature request with an example, please provide a sample application via one of the following means: -->

* Preferably, a CodeSandbox forked from https://codesandbox.io/s/github/marmelab/react-admin/tree/master/examples/simple
* A link to a GitHub repo with the minimal codebase to reproduce the issue


insert short code snippets here


**Other information:**
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. For visual or layout problems, please include images or animated gifs.-->

**Environment**

* React-admin version:
* Last version that did not exhibit the issue (if applicable):
* React version:
* Browser:
* Stack trace (in case of a JS error):

Please follow it, including a link to a modified Codesandbox that shows the problem.

@DanielSanchez94
Copy link
Author

https://stackoverflow.com/questions/66532454/permission-disables-the-option-to-add-routes-to-customroutes-in-app-js

What you were expecting:
I would have an Admin with the customRoutes property that would declare my customized login screens (they are accessed without authentication), on the other hand, the rest of the screens that I created, with the react-admin template (they are accessed with authentication) would show them to follow The permissions that the user has once logged in (I solve the authentication with firebase).

What happened instead:
Now my problem is that when I add a customRoutes with my custom routes and return a set of resources depending on the user's permissions, then the custom routes stop working (they are automatically redirected to / login).

Steps to reproduce:
The problem is "solved" by returning a resource without the condition of having a particular permission: as follows

            <Admin 
                title="Simple Comercio"
                theme={ MyTheme } 
                disableTelemetry
                catchAll={ NotFound }
                authProvider= { authProvider }
                i18nProvider={ i18nProvider }
                layout={ MyLayout } 
                dataProvider={ adapterDataProvider } 
                loginPage={ MyLogin } 
                customRoutes={[
                    <Route
                        exact
                        path="/signup"
                        component={(props) => <SignUpForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/forgot-password"
                        component={(props) => <ForgotPasswordForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/reset-password"
                        component={(props) => <ResetPasswordForm {...props} />}
                        noLayout
                    />,
                ]}
                >
                { permissions => [
                    permissions.hasOwnProperty('admin') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />,
                        <Resource {...sellers} />,]
                    :null,
                    permissions.hasOwnProperty('seller') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />]
                    :null,
                ],  <Resource 
                            name="product" 
                            options={{ label: 'Productos'}} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>}
                 
            </Admin>

But I don't want to return any resource without the user having permissions
Related code:

5036 y # 4821 son el mismo problema.

import React from 'react';
import { Admin, Resource } from 'react-admin';
import adapterDataProvider from './auth/adapterDataProvider';
import i18nProvider from './i18n/es';
import categories from './categories';
import sellers from './sellers';
import MyLayout from './globalTheme/MyLayout';
import MyTheme from './globalTheme/MyTheme';
import authProvider from "./auth/authProvider";
import MyLogin from './login/MyLogin';
import { Route } from 'react-router-dom';
import SignUpForm from './login/SignUpForm';
import ForgotPasswordForm from './login/ForgotPasswordForm';
import NotFound from './globalTheme/NotFound';
import ResetPasswordForm from './login/ResetPasswordForm';
import ShopIcon from '@material-ui/icons/Shop';
import ProductCreate from './products/create';
import ProductEdit from './products/edit';
import { ProductList } from './products/products';

const App = ( ) => (
        <div> 
            <Admin 
                title="Simple Comercio"
                theme={ MyTheme } 
                disableTelemetry
                catchAll={NotFound}
                authProvider= { authProvider }
                i18nProvider={ i18nProvider }
                layout={ MyLayout } 
                dataProvider={ adapterDataProvider } 
                loginPage={ MyLogin } 
                customRoutes={[
                    <Route
                        exact
                        path="/signup"
                        component={(props) => <SignUpForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/forgot-password"
                        component={(props) => <ForgotPasswordForm {...props} />}
                        noLayout
                    />,
                    <Route
                        exact
                        path="/reset-password"
                        component={(props) => <ResetPasswordForm {...props} />}
                        noLayout
                    />,
                ]}
                >
                { permissions => [
                    permissions.hasOwnProperty('admin') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />,
                        <Resource {...sellers} />,]
                    :null,
                    permissions.hasOwnProperty('seller') ?
                        [<Resource 
                            name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />]
                    :null
                ] }
            </Admin>
        </div>
)
export default App;

@fzaninotto
Copy link
Member

@DanielSanchez94 If you want us to pay attention to your bug report, please include a link to a working codesandbox showing your problem, as explained in the issue template. The code you pasted can't be run.

Also, if you need rapid feedback, I suggest you subscribe to the Enterprise Edition of the framework. If you don't, please refrain from updating your issue like you just did - it creates noise, and we have enough of that.

@DanielSanchez94
Copy link
Author

https://codesandbox.io/s/zen-lamarr-i3b9d?file=/src/App.js

This is an example. I understand that the login doesn't work, but the link to "/prueba" should work.

@fzaninotto
Copy link
Member

Your codesandbox is incorrect. You're returning resources in an array of arrays. Also, when you don't want to return any resource, you must return an empty array, not null. And when returning an empty array, react-admin displays the loading screen (which you can customize).

https://codesandbox.io/s/competent-antonelli-fmi1w?file=/src/App.js

@miguelcorreia19
Copy link

@fzaninotto is normal access a custom route without login?
How I can put redirecting to login when auth check returns a rejection?
Thanks!

@fzaninotto
Copy link
Member

a custom route with no layout is accessible without authentication. If you want to check authentication in such routes, use the useAuthenticated hook (https://marmelab.com/react-admin/Authentication.html#useauthenticated-hook).

@miguelcorreia19
Copy link

But without the property noLayout, like in the demo example:

<Route exact path="/configuration" render={() => <Configuration />} />,
<Route exact path="/segments" render={() => <Segments />} />,

you can access those custom pages (/segments and /configuration) without login like the following link:

https://marmelab.com/react-admin-demo/#/configuration.

Btw, useAuthenticated hook can resolve. Maybe is some breaking change that I don't have read and sorry for that!

@DanielSanchez94
Copy link
Author

i resolve this issue of this way:


    <Admin 
        title="Simple Comercio"
        theme={ MyTheme } 
        disableTelemetry
        catchAll={ NotFound }
        authProvider= { authProvider }
        i18nProvider={ i18nProvider }
        layout={ MyLayout } 
        dataProvider={ adapterDataProvider } 
        loginPage={ MyLogin } 
        customRoutes={ customRoutes }
        dashboard={ Dashboard }
        >
            { permissions => { 
                if (!permissions) {
                    return [[]];
                }
                if (permissions.hasOwnProperty('admin'))
                    return [
                        <Resource name="product" options={{ label: 'Productos', permissions: permissions }} list={ ProductList } icon={ ShopIcon }/>,
                        <Resource {...categories} />,
                        <Resource {...sellers} /> ]
                if (permissions.seller)
                    return [
                        <Resource name="product" 
                            options={{ label: 'Productos', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />]
                if (permissions.hasOwnProperty('seller') && !permissions.seller)
                    return [
                        <Resource name="product" 
                            options={{ label: 'Productosss', permissions: permissions }} 
                            list={ ProductList } 
                            create={ ProductCreate } 
                            edit={ ProductEdit } 
                            icon={ ShopIcon }/>,
                        <Resource {...categories} />]
                }
            }


    </Admin>

Which leads me to think that there is something missing in the documentation, which happens when the Admin does not enter under any conditions, then nothing returns. There, it breaks and stops working, even the routes defined in the customRoutes.

In the documentation example, just return Resources with no conditions, then there is no problem. But, if you want to add conditions like me then this won't work. unless it returns [[]]

@DanielSanchez94
Copy link
Author

DanielSanchez94 commented Apr 7, 2021

I reopen this issue, since I run into the same problem again.

When I access my site: mysite.com.ar it throws me an authentication error, since it is also the path of the dashboard. so the checkAuth returns a reject and redirects to / login.

But it is the first time that the user enters, what I want is for the landingPage to be mysite.com.ar. and that it automatically redirects to mysite.com.ar/login.

The problem is that as I detail previously I use permissions to access different resources, if you don't have resources, then I must resolve [[]], otherwise it doesn't work. The links I declare in customRoutes all redirect to / login automatically.

Any solution? there has to be some general way to solve this.

Clarification: my project is developed with firebase, with the react-admin-firebase library

@DanielSanchez94
Copy link
Author

My App.js is

import React from 'react';
import { Admin, Resource } from 'react-admin';
import adapterDataProvider from './auth/adapterDataProvider';
import i18nProvider from './i18n/es';
import categories from './categories';
import sellers from './sellers';
import MyLayout from './globalTheme/MyLayout';
import MyTheme from './globalTheme/MyTheme';
import MyLogoutButton from './globalTheme/MyLogoutButton';
import authProvider from "./auth/authProvider";
import MyLogin from './login/MyLogin';
import NotFound from './globalTheme/NotFound';
import ShopIcon from '@material-ui/icons/Shop';
import ProductCreate from './products/create';
import ProductEdit from './products/edit';
import ProductShow from './products/show';
import { ProductList } from './products/products';
import customRoutes from './customRoutes';
import Dashboard from './dashboard/dashboard';
import { Redirect } from 'react-router-dom';

const App = ( ) => (
    <Admin 
        title="Simple Comercio"
        theme={ MyTheme } 
        disableTelemetry
        catchAll={ NotFound }
        authProvider= { authProvider }
        i18nProvider={ i18nProvider }
        layout={ MyLayout } 
        dataProvider={ adapterDataProvider } 
        loginPage={ MyLogin } 
        customRoutes={ customRoutes }
        logoutButton={MyLogoutButton}
    >
        { permissions => { 
            console.log("permissions", permissions);
            if (!permissions) {
                return [[]];
            }
            if (permissions.hasOwnProperty('admin'))
                return [
                    <Resource name="product" 
                        options={{ label: 'Productos', permissions: permissions }} 
                        list={ ProductList } 
                        show={ ProductShow } 
                        icon={ ShopIcon }
                        edit={ ProductEdit }
                        create={ ProductCreate }/>,
                    <Resource {...categories} />,
                    <Resource {...sellers} /> ]
            if (permissions.seller)
                return [
                    <Resource name="product" 
                        options={{ label: 'Productos', permissions: permissions }} 
                        list={ ProductList } 
                        create={ ProductCreate } 
                        edit={ ProductEdit } 
                        icon={ ShopIcon }/>,
                    <Resource {...categories} /> ]
            if (permissions.hasOwnProperty('seller') && !permissions.seller)
                return [ <Redirect to="/seller-pending" /> ]
            if (permissions)
                return [ <Redirect to="/role-option" /> ]
            }
        }
    </Admin>
)

export default App;

and my customRoutes.js is


import * as React from "react";
import { Route } from 'react-router-dom';
import SignUpForm from './login/SignUpForm';
import ForgotPasswordForm from './login/ForgotPasswordForm';
import ResetPasswordForm from './login/ResetPasswordForm';
import SellerForm from './login/SellerForm';
import RoleOption from "./login/RoleOption";
import SellerPending from "./login/SellerPending";
import Dashboard from "./dashboard/dashboard";
import MyLogin from './login/MyLogin';

const customRoutes = [      
    <Route
        exact
        path="/signup"
        component={(props) => <SignUpForm {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/forgot-password"
        component={(props) => <ForgotPasswordForm {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/reset-password"
        component={(props) => <ResetPasswordForm {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/seller-form"
        component={(props) => <SellerForm {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/role-option"
        component={(props) => <RoleOption {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/seller-pending"
        component={(props) => <SellerPending {...props} />}
        noLayout
    />,
    <Route
        exact
        path="/home"
        component={(props) => <Dashboard {...props} />}
    />,
    <Route
        exact
        path="/"
        component={(props) => <MyLogin {...props} />}
        noLayout
    />,
];

export default customRoutes;

@DanielSanchez94
Copy link
Author

DanielSanchez94 commented Apr 7, 2021

To test the error, you must enter https://simplecomercio.tk, what happens is that when you are in that path, you do not have permissions, so when you log in, you enter the case
if (!permissions) { return [[]]; }so it doesn't show me the resources it should show me.

@fzaninotto
Copy link
Member

I think you just need to upgrade to 3.14.2 (see #6112).

also: this is an English tracker. Even though some of us speak other languages, for the sake of the community, only English is accepted.

@DanielSanchez94
Copy link
Author

DanielSanchez94 commented Apr 9, 2021

Update packege-lock.json to the latest version. The problem persists.

One time more, if i do this:
case (!permissions) : return [ <Redirect to="/login" /> ]; customRoute routes involuntarily redirect to / login automatically, without being able to see the views.

If i do this:
case (!permissions) : return [ ]; in "http://localhost:3000/#/" Display the white page.

And if I do this:
case (!permissions) : return [ [ ] ]; in "http://localhost:3000/#/" Redirect to /login but show notification "ra.auth.auth_check_error"

What I want is to enter http://localhost:3000/#/ and not return an error when redirecting to http://localhost:3000/#/login (because in this case I should not do the check in checkAuth). At the same time I want the customRoutes links to continue working.

thanks for reading my concerns.

@fzaninotto
Copy link
Member

This is really a "how to" question and not a bug request. So I'm closing the issue here, please continue the discussion on StackOverflow.

@gabrielperales
Copy link

gabrielperales commented Jun 8, 2021

I'm having the same issue. The problem comes when Admin is being used with permissions and renderProps. Seems like when you are using it with renderProps it has to be checking if
the user is logged in, and if he isn't it redirects to /login.

I'm also getting this message in the console when I try to go to a customRoute when I'm using Admin with renderProps:

Captura de pantalla 2021-06-08 a las 18 43 37

  • The upper codesandbox from @DanielSanchez94 is a good example, so this is not working right:

codesandbox.io/s/epic-kepler-cii3c

  • Meanwhile my version without using renderProps works as expected

codesandbox.io/s/determined-torvalds-l48rl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants