I have a function that redirects a user to a page Orders
if the user's state is complete
, and to a HOME
page if the user's state is not complete
.
The Orders
page has a GuardService
that implements canActivate
, and the HOME
page does not have any guards.
I have some users with the R_ORDERS
right and in a complete
state who are not navigating at all. (ie they are neither routed to the Orders
page nor the HOME
page).
I can see that the HTTP requests retrieving the user's right is called but they are stuck in that page.
Is my issue related to this post ? enter link description here
or to this article enter link description here
Also, I have tried to add logs when the observable has completed but in that case, the log is never displayed in the console.
return this.getList().subscribe((e) => {
const right = new List(e).FirstOrDefault(
(d) => d.code == securizedPath.keyCode
)?.type;
if (!right) return resolve("OFF");
return resolve(right);
},
(error) => {
console.log("Right store threw an error");
console.log(error);
},
() => {
console.log("Right list completed")
}
);
thanks for your help
async redirectTo() {
this.loading = true;
this.userState = await this.stateService.getToPromise(this.userId);
if (this.userState.isComplete) {
this.orderService.init();
this.router.navigate([RouteNames.ORDERS]);
this.loading = false;
return;
}
this.router.navigate([RouteNames.HOME]);
return;
}
The RouteNames.ORDERS
has the following guard:
@Injectable({
providedIn: "root",
})
export class GuardService implements CanActivate {
constructor(
private router: Router,
private rightService: UserRightService
) {}
canActivate(
route: import("@angular/router").ActivatedRouteSnapshot,
state: import("@angular/router").RouterStateSnapshot
):
| boolean
| import("@angular/router").UrlTree
| import("rxjs").Observable<boolean | import("@angular/router").UrlTree>
| Promise<boolean | import("@angular/router").UrlTree> {
return this.test(route);
}
async test(route: ActivatedRouteSnapshot) {
const right = await this.rightService.isRouteAllowed(route.url[0].path);
if (right == "OFF") {
this.router.navigate([RouteNames.FEATURE_UNAUTHORIZED]);
return false;
} else if (right != "ON") {
this.router.navigate([RouteNames.FEATURE_UNAUTHORIZED]);
return false;
}
return true;
}
}
Code for the UserRightService
is
isRouteAllowed(route: string): Promise<Right> {
const securizedPath = new List(this.securizedPaths).FirstOrDefault(
(e) => e.name == route
);
return new Promise((resolve) => {
return this.getList().subscribe((e) => {
const right = new List(e).FirstOrDefault(
(d) => d.code == securizedPath.keyCode
)?.type;
if (!right) return resolve("OFF");
return resolve(right);
});
});
}
securizedPaths
is defined as below
typescript[{ name: RouteNames.ORDERS, keyCode: "R_ORDERS" }, // other value ]
and getList is
getList() {
this.subjectList = new ReplaySubject<T[]>();
this.load();
return this.subjectList;
}
protected load() {
return this.getService()
.getAll()
.then((e) => {
this.subjectList.next(e);
})
.catch((e) => {
this.subjectList.next([]);
this.subjectList = null;
});
}
// Code for this.getService().getAll()
async getAll(id?: any, parameter?: any): Promise<Array<T>> {
let urlParameters;
({ urlParameters, parameter } = this.createParameters(parameter, id));
return this.http
.get(this.url + (urlParameters ? "?" + urlParameters : ""))
.toPromise<Array<T>>();
}
I am NOT* sure whether i understand your problem completely but based on reading i see something which i would like to propose you. I see some issue in GuardService
@Injectable({
providedIn: "root",
})
export class GuardService implements CanActivate {
constructor(
private router: Router,
private rightService: UserRightService
) { }
canActivate(
route: import("@angular/router").ActivatedRouteSnapshot,
state: import("@angular/router").RouterStateSnapshot
): Promise<boolean> {
let resolver: (value: boolean | PromiseLike<boolean>) => void;
const promise = new Promise<boolean>((resolve) => {
resolver = resolve;
});
this.test(route, resolver);
return resolver;
}
async test(route: ActivatedRouteSnapshot, resolver: (value: boolean | PromiseLike<boolean>)) {
const right = await this.rightService.isRouteAllowed(route.url[0].path);
if (right == "OFF") {
this.router.navigate([RouteNames.FEATURE_UNAUTHORIZED]);
return resolver(false);
} else if (right != "ON") {
this.router.navigate([RouteNames.FEATURE_UNAUTHORIZED]);
return resolver(false);
}
return resolver(true);
}
}
See code I have highlighted in bold.
I guess you must return a promise which will resolved in test method based on what value will be received in response.
My proposal is totally based some assumption which helped me to fix an issue in past where CanActivte method of the Gurad wanted to return a value asynchronously.