Redirecting to previous route after login - Couldn't redirect for Product Detail - spartacus-storefront

After successfully logging in, I need to redirect the user to route that they came from. As I have read AuthRedirectService is built for this but when I move into product detail then hit login and do a successful login, it just redirects me into root page instead of product detail page. But it works for other pages in the application. anybody can help me about that ? thanks

The recommended way to protect CMS pages is to configure a guard for any CMS component that appears in this page. For instance, you can protect Product Details Page, by configuring the AuthGuard for ProdcutIntroComponent (that is likely appearing only in PDP), i.e. in your app.module:
import { ConfigModule, AuthGuard } from '#spartacus/core';
/*...*/
imports: [
ConfigModule.withConfig({
cmsComponents: {
ProductIntroComponent: {
guards: [AuthGuard]
},
},
}),
],
There is no need to customize or touch AuthRedirectService.

The redirect URL in Spartacus is added by the NotAuthGuard, that is by default configured on the ReturningCustomerLoginComponent CMS component. Perhaps you have a customised version of the login component and have not configured this guard?
You can follow the default code from the following pointers:
https://github.com/SAP/spartacus/blob/develop/projects/storefrontlib/src/cms-components/user/login-form/login-form.module.ts
https://github.com/SAP/spartacus/blob/develop/projects/core/src/auth/guards/not-auth.guard.ts
https://github.com/SAP/spartacus/blob/develop/projects/core/src/auth/guards/auth-redirect.service.ts#L59

Related

Custom PageLayoutComponent

To have specific layout for some pages at our project we create few custom PageLayoutComponent's. Some contfiguration example:
{
// #ts-ignore
path: null,
canActivate: [CmsPageGuard],
component: CartPageLayoutComponent,
data: {
cxRoute: 'cart',
cxContext: {
[ORDER_ENTRIES_CONTEXT]: ActiveCartOrderEntriesContextToken,
},
},
},
All work fine with storefront until you will not try to select specific page at smartedit. As result it not use our custom CartPageLayoutComponent, but will use PageLayoutComponent for rendering.
Probably this is because it's not a normal route navigation. Can somebody from spartacus team suggest how this bug can be fixed?
Probably this is because it's not a normal route navigation
I believe your Route should be recognized normally, there is nothing special in adding a custom Angular Route.
So I guess there is something special about the page or URL of Spartacus Storefront that runs in your SmartEdit.
It's hard to tell the reason of your problem without more debugging.
You said your app works as expected when run differently (locally?), but when used in SmartEdit, then there is a problem. Please identify factors that makes the run SmartEdit different from your (local?) run. And try to isolate them. Guesses from top of my head:
production vs dev mode of the build?
exact URL of the cart page?
any difference in configuration between a local version and deployed one to be used in SmartEdit?
I would also add some debugging code to better know which routes configs are available and which one is used for the current route. For debugging purposes please add the following constructor logic in your AppModule:
export class AppModule {
// on every page change, log:
// - active url
// - the Route object that was matched with the active URL
// - all the Route objects provided to Angular Router
constructor(router: Router) {
router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
console.log({
activeUrl: router.url,
activeRouteConfig:
router.routerState.snapshot.root.firstChild.routeConfig,
allRoutesConfigs: router.config,
});
}
});
}
}
The pages opened in SmartEdit have the same route of cx-preview (e.g. to open faq page in smartedit, request is https://localhost:4200/electronics-spa/en/USD/cx-preview?cmsTicketId=xxxxx. backend can get page id from cmsTicketId). If you want to change the page layout, you can consider use PageLayoutHandler. Spartacus has some PageLayoutHandlers, e.g.
{
provide: PAGE_LAYOUT_HANDLER,
useExisting: CartPageLayoutHandler,
multi: true,
},

Vue-Routes redirect doesn't work and beforeEnter render App component again

I'm getting some issues when trying to redirect to an external link.
for ex:
{ path: '*', redirect: 'https://google.com'}
when I use "redirect" it doesn't work completely, but when I use something like that
{ path: '/*',
beforeEnter(to, from, next) {
window.location = "https://google.com"
}
}
it works but there is a problem because first, it tries to render App component again but there is no component so be empty and a blank page is being rendered for nearly 1-1.5 second then it redirects to target URL and I don't want it to reload App component, just redirect it to other link. I googled but found nothing noteworthy.
Or maybe is there another way like deactive a component or use v-if or directly rendering a html file?
redirect is meant to redirect to another route defined by your application, not to go to another website directly.
window.location works, but I think the behavior is somewhat browser-dependent.

Nuxt - How can I run a code in client-side after server-side-rendering?

I created a plugin injecting a noty (https://ned.im/noty/#/) so I can use it globally, it looks like this:
export default ({ app }, inject) => {
const notify = function (options = {}) {
if (process.client) {
new Noty(options).show();
}
}
app.$notify = notify;
inject('notify', notify);
}
This plugin shows a noty only on the client-side. On the server-side a noty does not appear, cause it can be displayed only in browser.
I have a page with product details and I am receiving data in asyncData method. When the product was not found I would like to show a noty with proper message and redirect user to a product list page. When I change a route in client-side everything works awesome. However on the first page load (eg. I change an url manually in the browser) which happens on the server-side a noty does not appear, only a redirect works.
My question is: how to show a noty in this case? How to create a noty in the browser after SSR or what is the best other solution to my problem?
Is there any way to run some code after client-side is already rendered (after server-side-rendering)?
You could just disable ssr for that plugin.
plugins: [
...,
{ src: '~plugins/yourplugin.js', ssr: false }
]
Okay, I found a module for that: https://github.com/potato4d/nuxt-client-init-module
it's not possible right know (nuxt <= 2.14.0 when i answering)
but you can combine client plugin and client middleware to achieve that
please take a look at this link:
https://github.com/nuxt/nuxt.js/issues/2653#issuecomment-390588837

Is there a more comprehensive way to handle authentication in Angular2 rc3 than guards?

I have an existing Angular2 app where login/authentication was handled by creating an AuthRouterOutletDirective that extended the RouterOutlet. This made it easy to use componentInstruction in the activate function to check if a user was logged in, if not redirect them to our login portal (for various reasons I have no control over this is through a separate app, which has it's own login screen and then sends back a token that we would save in the Angular2 app) before navigating to the next component.
I just upgraded to the router 3.0.0-alpha.8 and I see that this is no longer an option and it has been replaced by creating an authGuard and and using the canActivate method to handle authentication (I'm referring to this section of the documentation). The problem I'm struggling with is it seems like this is designed for apps where only a small number of routes are protected, and you can just add canActivate: [AuthGuard] to each route that requires authentication in the RouterConfig.
The problem I'm having is that every single route needs to be protected by authentication. There also needs to be continuous checking (unless there is a better fix) because we also (again due in part to the external login service we have to use) will log out the users and clear their token and the next time you navigate to a new route (regardless of what the route is) it should redirect you to login again. I understand that I could just add canActivate: [AuthGuard] to every single route but that seems like an insane and tedious fix, especially for apps with a large amount of routes, all of which require a user to be authenticated to view.
I've been searching for a fix but it seems like, perhaps in part because the upgrade is fairly new, that all the resources are for how to implement these AuthGuards on just one or two routes. I've been digging through the source code (specifically here) to see if there is another method I can extend that's more comprehensive than canActivate or a more universal way to have every route include a particular guard but I can't seem to find anything. Any advice on how best to implement this would be very much appreciated! Thanks.
Referring to my comment, you can add extra guard like that:
import {provideRouter, RouterConfig, Route, CanActivate, ActivatedRouteSnapshot} from '#angular/router';
import {Injectable} from "#angular/core";
#Injectable()
class UniversalGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot) {
console.log('applying can activate');
return true;
}
}
let routes: RouterConfig = [
{path: 'path1', component: Component1} as Route,
{path: 'path2', component: Component2} as Route,
{path: 'path3', component: Component3} as Route
];
const routeAugumenter = route => {
let guards = route.canActivate || [];
guards.push(UniversalGuard);
route.canActivate = guards;
if (route.children) {
route.children = route.children.map(routeAugumenter);
}
return route;
};
let augumentedRoutes = routes.map(routeAugumenter);
console.log(augumentedRoutes);
export const APP_ROUTER_PROVIDERS = [
provideRouter(augumentedRoutes), UniversalGuard
];
I have not tested it with child routes, but should work as well.
Edit: updated information how to inject services into UniversalGuard.
If your guard needs some services injected, you inject them in the constructor, as usually. You have to provide these services (and the services they depend on, etc.) in Angular bootstrap call rather than in the components.

Aurelia Redirection to the anonymous page or any other page with default access-token without going to login page....?

I developing a demo app which is having a login page., By default I am loading to that default page. But For some pages I want to go with the URL directly redirect to that page. But aurelia default loading to the login page. How can I redirect to the anonymous URL or some URL with my token directly without going to Login page.
Can anyone explain me or give a sample ?
You can use canActivate()
canActivate(params, routeConfig, navigationInstruction) {
//some check for token in params
if (hasToken) {
return new Redirect(`/someroute/${token}`);
}
// proceed and load login page
}
or you can use different routes like
{ route: 'login', moduleId: './pages/login'},
{ route: 'login/token/:token', moduleId: './pages/anonym'},