Hi, After adding this to the context / auth / bac...
# gooddata-ui
m
Hi, After adding this to the context / auth / backend.js file export const createBackend = () => { return withNormalization(withCaching(bearFactory(backendConfig).withAuthentication(new ContextDeferredAuthProvider()), RecommendedCachingConfiguration)); }; This line fails on the home.js route for SSO, but was working before import { useBackend } from "../contexts/Auth/context"; [...] const { sdk: backend } = useBackend(); const relayState = "https://rentaleye.central.sc/"; useEffect(() => { backend.user.isLoggedIn().then((isLogged) => { if (!isLogged) { process.env.REACT_APP_SET_HOSTNAME && backend.user.initiateSamlSso(relayState); } }); }); Cannot read properties of undefined (reading 'user')
m
Hello @Michael Serres I think, that you should wrap the backend first, and set the authentication in the top layer, eg:
Copy code
const decoratedBackend = withNormalization(
    withCaching(
        bearFactory(backendConfig),
        RecommendedCachingConfiguration),
    )
);

const backendWithAuth = decoratedBackend.withAuthentication(...)
m
Thanks @Matyáš Kandl but it doesn't work. Somehow after applying caching and normalisation, backend is always undefined. So I never get the redirect to Auth0 on server. Locally work by adding '?.' because it goes via proxy. import { useBackend } from "../contexts/Auth"; const Home = () => { const { sdk: backend } = useBackend(); const relayState = "https://rentaleye.central.sc/"; console.log(backend); <--- undefined useEffect(() => { backend?.user.isLoggedIn().then((isLogged) => { if (!isLogged) { process.env.REACT_APP_SET_HOSTNAME && backend.user.initiateSamlSso(relayState); } }); }, [backend]);
If I remove, caching/normalisation, works on local and server
@Matyáš Kandl Using this seems to work... Not sure if that's recommended... must be because of the normalisation and caching... const { decorated: { decorated: { sdk: backend }, }, } = useBackend();
d
Hi, @Michael Serres I am just wondering why do you need to access the
sdk
property directly? Can you use
Copy code
import sdk from "@gooddata/api-client-bear";

const backend = useBackend();
const relayState = "<https://rentaleye.central.sc/>";
// ...
const isLoggedIn = backend.isAuthenticated().then((isLogged) => {
    if (!isLogged) {
        process.env.REACT_APP_SET_HOSTNAME &&
            sdk.user.initiateSamlSso(relayState);
    }
});
That way you will use the
backend
object as intended: in a backend-implementation-agnostic fashion and you would only use the backend-specific functionality to do the backend-specific SSO call. Accessing the
sdk
property of the
backend
object is discouraged as it is a private property and can be removed in future releases (it also is not “forwarded” by the decorators as you encountered). Cc @Matyáš Kandl
Alternatively, you could implement a custom
IAuthenticationProvider
and use it instead of the
ContextDeferredAuthProvider
you currently use. There, you could implement the
authenticate
method yourself, triggering the SSO flow from there (the
IAuthenticationProvider
has better access to the
sdk
object you can use to make the SSO call). See the existing ContextDeferredAuthProvider implementation for some inspiration, there you would replace the NotAuthenticated error by the SSO call using the
sdk
object.
m
Hi @Dan Homola I think I understand what you're saying, will try the way described above, appreciate greatly the tips
👍 1
Hi @Dan Homola I have an issue with an export pivot table, works on localhost but fails once I deploy on server. Might be related to how I instantiate the backend. Export goes to a blank page with this error in console. Failed to load resource: the server responded with a status of 404 (Not Found) https://rentaleye.central.sc/gdc/exporter/result/gb3phb0ky787mqamchzqrnglx0dgrnct/a6fb4cf5bdbfb49ab79be0e92c2fd2d500000023
d
Hi, this is most likely caused by the fact you have the
backend
instance misconfigured. You used the
@gooddata/create-gooddata-react-app
to create your app, right? If so, please make sure you are using the
build-with-explicit-hostname
npm script to build your app (not the plain
build
). This should make sure your app will work properly even when deployed. More details should be available at the end of the README.md file of your created app.
m
Thanks @Dan Homola I don’t think that’s the reason, I follow those steps closely to deploy to server.
Is there additional config in the api to add a domain to allowed exports list?
d
The problem is not allowed domains. The problem is that the exportign code tries to get the export result on https://rentaleye.central.sc which is not where you have your GoodData instance, right? And the explicit hostname should make it so that this accesses the GoodData instance directly. What is the value of the
backend
value in your
src/constants
file?
m
const backend = “https://experteye.on.gooddata.com”;
d
🤔 that is very strange, the value is correct, the build is run with the explicit hostname passing and yet it tries to go to the wrong URL. What version of GoodData.UI do you have? There was a fix in this area recently, so maybe you have a version with a bug here? I think the version that has this fixed is 8.11.0
m
“@gooddata/sdk-backend-bear”: “^8.11.0",
That’s what’s I’m saying… everything works except the export
d
I am running out of ideas 😕 can you please share the code you are using to export the table?
m
<ChartWithExport filters={currentFilter}> {(onExportReady) => ( <div style={{ height: 800 }} className=“s-line-chart”> <PivotTable measures={measures} rows={rows} filters={currentFilter} config={{ columnSizing: { defaultWidth: “autoresizeAll”, growToFit: true, }, }} onExportReady={onExportReady} /> </div> )} </ChartWithExport>
ChartWithExport is a copy paste of the example in the gd.ui docs
d
m
Yes this last one
👀 1
d
Oh, I see it now, it does not have the fix I was talking about applied to it and it works just because of how the examples application is set up (a bit of a non-standard way). Sorry about that 😞 You need to explicitly prepend your domain to the result URL. So instead of
Copy code
const getExportUri = async () => {
    try {
        return (await exportFunction(exportConfig!))?.uri;
    } catch (error) {
        let errorMessage = error.message;
        if (error.responseBody) {
            errorMessage = JSON.parse(error.responseBody)?.error?.message;
        }
        throw errorMessage;
    }
};
please try
Copy code
const getExportUri = async () => {
    try {
        const relativeUri = (await exportFunction(exportConfig!)).uri;
        // when running on custom hostname, explicitly prepend it
        // otherwise the export result would be loaded from wrong origin
        return backend.config.hostname
            ? new URL(relativeUri, backend.config.hostname).href
            : relativeUri;
    } catch (error) {
        let errorMessage = error.message;
        if (error.responseBody) {
            errorMessage = JSON.parse(error.responseBody)?.error?.message;
        }
        throw errorMessage;
    }
};
where
backend
can be obtained using the
useBackendStrict
hook from
@gooddata/sdk-model
We will fix this in the examples so that it does not confuse anyone else. Sorry again 😕