Using a service in angular 4 guards - angular-guards

Please assist with angular guards, I have the following angular Guard below :
export class RoleGuard implements CanActivate {
private role: any;
constructor(private router: Router, private accountService: AccountService)
{}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
this.accountService.getUserRole().subscribe(res => this.role = res);
if (this.role === 'admin') {
return true;
}
return false;
}
}
in the service:
getUserRole(): Observable<Response> {
const options = this.headers();
return this.http.get(`${environment.ApiUrl}/Roles/getRole`,options)
.map(res => res.json())
.catch(res => Observable.throw(res.json()));
}
I am trying to subscribe to the getUserRole() function, then assign the response to this.role but that is not happening, role is always undefined. when i do a ...subscribe(res => console.log(res)) i see the response data.

You have to wait the result of the async HTTP Request before check if can activate that route or not.
Try returning a new Observable instead:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return new Observable(observer => {
//
this.accountService.getUserRole().subscribe(role => {
//
if (role === 'admin') {
observer.next(true); // Allowing route activation
} else {
observer.next(false); // Denying route activation
}
}, err => observer.next(false));
});
}

Related

Why is the response available in a service but in the component is undefined? [duplicate]

This question already has an answer here:
Component does not receive Data from Service
(1 answer)
Closed 5 years ago.
I have a service and a component which uses the service.The issue is that in a service I can read the response which is as JSON object. But in the Component, I get the following: res: undefined.
service:
constructor(
private http: Http,
private fbuilder: FormBuilder,
private user: UserService
) {}
login(uname:string, pass:string): Observable<any> {
let headers = new Headers({
'Content-Type': 'application/json',
'Username':uname,
'Password':pass
});
let options = new RequestOptions({ headers: headers });
let data = {};
var Observable = this.http.post( url, data, options )
.map(res => {
res.json();
})
.catch( (error: any) => Observable.throw(error.json().error || 'Server error') );
return Observable;
}
component:
constructor(
private http: Http,
private fbuilder: FormBuilder,
private user: UserService
) {}
loginUser(uname: string, pass: string) {
this.user.login(uname, pass).subscribe(
res => {
console.log('res: ' + JSON.stringify(res));
},
err => {
this.errorMessage = err;
}
);
}
It looks like your problem is with this code:
.map(res => {
res.json();
})
You're not returning the result of res.json. You just need to add the return statement, like so:
.map(res => {
return res.json();
})
You could also just remove the {} pair, like so:
.map(res => res.json())

Angular2 Authentication : there's something wrong with POST request?

Hi I am trying to authenticate users and once the server gives user's information, I want to use the information of the user.
But for some reasons, even though I did the log in process without any error and I can see from developer's tool that the POST request has been successful, I can't quite set currentUser in my localStorage (giving me null if I console.log it)
What am I doing wrong?
This is my authentication service.
export class AuthenticationService {
constructor(private http: Http, private router: Router) { }
login(email: string, password: string): Observable<User>{
const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
headers.append('Access-Control-Allow-Headers', 'Content-Type');
headers.append('Access-Control-Allow-Methods', 'post');
headers.append('Access-Control-Allow-Origin', '*');
headers.append("X-Requested-With", "XMLHttpRequest");
let options = new RequestOptions({ headers: headers });
let body = new URLSearchParams();
body.set('email', email);
body.set('password', password);
return this.http.post(`${environment.baseurl}` + '/api/v2/member/login', body, options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let user = res.json();
if (user && user.token) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
return user.data || {};
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
}
private handleError(error: any) {
if (error.status === 401) {
return Observable.throw(error.status);
} else {
return Observable.throw(error.status || 'Server error');
}
}
}
And this is my log-in component
export class LoginPageComponent implements OnInit {
constructor(private location: Location,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) {
}
model: any = {};
loading = false;
returnUrl: string;
error = '';
ngOnInit() {
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['main'] || '/';
}
currentUser: User;
login() {
this.loading = true;
this.authenticationService.login(this.model.email, this.model.password)
.subscribe(
data => {
this.currentUser = data;
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}
backClicked() {
this.location.back();
}
}
And this is my home component
export class MainComponent {
onClick() {
this.auth.logout() //if user clicks logout button
}
currentUser: User;
users: User[] = [];
items: Object[] = [];
constructor(private authguard: AuthGuard, private auth:AuthenticationService) {
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
console.log(localStorage.getItem('currentUser')); //Printing null
}
}
And the model for user information is this.
export interface User {
birthday: number;
email:string;
genderType:string;
memberType: string;
name: string;
phone: string;
}
What im receiving
Why is it printing null?
Thank you!
Mistakes you made
passing email and password as URLSearchParams.
You are adding all the headers to your login method which is not necessary
The service should contain method as below
login(body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.http.post('loginUrl', body);
}
Component should contain the below code
login() {
let user ={
email : this.model.email
password : this.model.password)
}
this.loading = true;
this.authenticationService.login(user)
.subscribe(data => {
this.authenticationService.extractData(data);///call to store token in the localstorage
this.router.navigate([this.returnUrl]);
},
error => {
this.error = "Wrong ID or PW";
this.loading = false;
});
}

how to manipulate localStorage parameters in ionic 2 i get undefined values

i have struggles with the local storage parameter i have this //error SyntaxError at JSON.parse ()// i get " undefined" instead of the real values any help please on how to retrieve parameters from LocalStorage that i set after login in both my service auth-service.ts and auth.ts??!!
auth-service.ts
public loginChef(credentials) {
if (credentials.email === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
return Observable.create(observer => {
var url = 'http://localhost/PFEBACKEND/login-chef.php?
email='+credentials.email+'&passe='+credentials.password ;
this.http.get(url).map(res => res.json()).subscribe(
data=>{
let access = (data.error=== 0 )
localStorage.setItem('nom',data.nom_contact);
localStorage.setItem('nom_societe',data.nom_societe);
localStorage.setItem('email',data.email);
localStorage.setItem('telephone',data.telephone);
localStorage.setItem('matricule_fiscale',data.matricule_fiscale);
localStorage.setItem('role',data.role);
localStorage.setItem('id',data.id_chef);
this.member=data;
this.email=data.email;
this.nom=data.nom;
// this.currentUser = new User( data.nom,data.email);
observer.next(this.email,this.nom);
//observer.next(this.member);
//observer.next(access);
// console.log(this.currentUser);
observer.complete();
},
err => {
console.log(err);
observer.next(err);
},
() => console.log('service observable') );
});
}
}
offre.ts
offres: Array<any>;
loader: any;
id:string='';
constructor(public navCtrl: NavController, public navParams: NavParams,
public data:Datamembers,private auth:AuthService, public
loadingCtrl:LoadingController)
{
if(localStorage.getItem('id')){//after login i store the user data
this.id=localStorage.getItem('id');
}
}
ngOnInit()
{ var id1=parseInt(this.id).valueOf();// i get undefined value
this.presentLoading();
this.data.LoadOffres(id1).subscribe(
//function LoadOffres accept int type parameter
data => {
this.offres = data;
console.log(data);
this.loader.dismiss();
},
err => {
console.log(err);
console.log(id1);
this.loader.dismiss();
},
() => console.log('chargement terminé')
);
}
auth.ts
public loginChef() {
this.showLoading();
this.auth.loginChef(this.registerCredentials).subscribe(allowed => {
if (allowed) {
setTimeout(() => {
this.email=this.auth.email;
this.nom=this.auth.nom;
this.currentUSer = this.auth.currentUser;
this.member=this.auth.member;//array
localStorage.setItem('email',this.email);
localStorage.setItem('nom',this.nom);
(....)
everything is right the problem was in my server side code

Angular2 and Web API session control

i'm doing a login service. But i'm only capable of doing login, but i want to make a session to control the login's.
Where is my login.component.ts:
#Component({
selector: 'login',
templateUrl: './app/login/login.component.html'
})
export class LoginComponent implements OnInit {
model: any = {};
loading = false;
returnUrl: string;
constructor(
private route: ActivatedRoute,
private router: Router,
private utilizadorService: UtilizadoresService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this.utilizadorService.logout();
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
login() {
console.log("Login! ");
this.loading = true;
this.utilizadorService.login(this.model.email, this.model.password).subscribe(
data => {
this.alertService.success('Login successful', true);
this.router.navigate(['/profile']);
},
error => {
this.alertService.error(error._body);
this.loading = false;
});
}
}
and there is my utilizadores.serice.ts, where is the login/register function:
#Injectable()
export class UtilizadoresService {
constructor(private _http: Http) {}
private RegenerateData = new Subject<number>();
// Observable string streams
RegenerateData$ = this.RegenerateData.asObservable();
AnnounceChange(mission: number) {
this.RegenerateData.next(mission);
}
LoadData(): Promise<IUtilizadores[]> {
return this._http.get('/api/utilizadores')
.toPromise()
.then(response => this.extractArray(response))
.catch(this.handleErrorPromise);
}
Add(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
delete model["id"];
let body = JSON.stringify(model);
return this._http.post('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Update(model: IUtilizadores) {
let headers = new Headers({
'Content-Type':
'application/json; charset=utf-8'
});
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify(model);
return this._http.put('/api/utilizadores/', body, options).toPromise().catch(this.handleErrorPromise);
}
Delete(id: number) {
return this._http.delete('/api/utilizadores/?id=' + id).toPromise().catch(this.handleErrorPromise);
}
login(email: string, password: string) {
return this._http.post('/api/utilizadores/login', { email: email, password: password })
.map((response: Response) => {
let utilizador = response.json();
if (utilizador) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(utilizador));
}
});
}
logout() {
// remove user from local storage to log user out
// localStorage.removeItem('id_token');
localStorage.removeItem('currentUser');
}
public authenticated() {
// Check if there's an unexpired JWT
// This searches for an item in localStorage with key == 'id_token'
return tokenNotExpired();
}
protected extractArray(res: Response, showprogress: boolean = true) {
let data = res.json();
return data || [];
}
protected handleErrorPromise(error: any): Promise<void> {
try {
error = JSON.parse(error._body);
} catch (e) {
}
let errMsg = error.errorMessage
? error.errorMessage
: error.message
? error.message
: error._body
? error._body
: error.status
? `${error.status} - ${error.statusText}`
: 'unknown server error';
console.error(errMsg);
return Promise.reject(errMsg);
}
}
export interface IUtilizadores {
id: number,
email: string,
nickname: string,
password: string
}
I'm doing this for a school project, so i dont want to work with Auth0, and i'm using VS 2015 and microsoft SQL server

Angular 2 - Return of Observable

I have problem with my Observable in my service.
I need to fetch data for 3 players. My subscription sign data from service to local variable and push it into array. Fine, but when i return data from if statement i have bug. I can see only one of 3 players. How can i store all data for whole life time of my app?
Regards.
Service:
getData(query): Observable<any> {
if(this.dataFromDb)
{
return Observable.of(this.dataFromDb);
}
return this.http.get(query)
.map(res => res.json())
.do(res => this.dataFromDb = res)
.catch(err => Observable.throw(err.json() || 'Błąd');
}
}
Component:
export class FriendsComponent implements OnInit {
myDataFromDb: any[] = [];
constructor(public dataService: DataService) {
}
private getDataFromDb(query) {
this.dataService.getData(query).subscribe((data) =>
{
this.myDataFromDb.push(data);
console.log(data);
});
}
ngOnInit() {
for (let i of this.dataService.friends) {
this.dataService.query = `${this.dataService.apiUrl}${i.nick}${this.dataService.apikey}`;
this.getDataFromDb(this.dataService.query);
}
console.log(this.myDataFromDb);
}
}
And some photo of problem:
Data on start
Data after route change.
You must use a object to "cache" the response. Personally I'll choose send to my function the nick and the apiKey, but as you send query, you can do
dataFromDb:any={};
getData(query): Observable<any> {
if(this.dataFromDb[query])
{
return Observable.of(this.dataFromDb[query]);
}
return this.http.get(query)
.map(res => res.json())
.do(res => this.dataFromDb[query] = res)
.catch(err => Observable.throw(err.json() || 'Błąd');
}
}