Logged in user can see only his own content (Angular+Firebase) - javascript

I have a file named user.service.ts with a following code (I set firebase authentication here):
export class UserService {
uid = this.afAuth.authState.pipe(
map((authState) => {
if (!authState) {
return null;
} else {
return authState.uid;
}
})
);
isAdmin: Observable<boolean>= this.uid.pipe(
switchMap(uid=>{
if(!uid){
return observableOf(false);
} else{
return this.firebase.object<boolean>('/admin/'+ uid).valueChanges()
}
})
);
constructor(private afAuth: AngularFireAuth, private firebase: AngularFireDatabase) {}
login() {
this.afAuth.auth.signInWithPopup(new auth.GoogleAuthProvider());
}
logout() {
this.afAuth.auth.signOut();
}
I have a file named employee.service.ts, and this is how I insert employees in firebase:
insertEmployee(employee) {
this.employeeList.push({
caseId: employee.caseId,
caseName: employee.caseName,
department: employee.department,
startDate: employee.startDate==""?"":this.datePipe.transform(employee.startDate, 'dd.MM.yyyy'),
startTime: employee.startTime,
finishTime: employee.finishTime,
isPermanent: employee.isPermanent,
description: employee.description,
remark: employee.remark,
serviceType: employee.serviceType,
isReplaceable: employee.isReplaceable,
maintainer: employee.maintainer,
contracts: employee.contracts,
dnevnica: employee.dnevnica,
client: employee.client
});
}
In the same file, I get employees like:
getEmployees(){
this.employeeList=this.firebase.list('employees');
return this.employeeList.snapshotChanges();
}
My question is: How I can connect this insert with client id? To be more concrete, I want to make every user see only his content, how can I do that?

Related

How to store data under specific user id? Angular&Firebase

it's been a while.
My question is how to store data in realtime database (firebase) by current logged in user id, so when I log in from another account, I can't see that data (only my own).
This is how I do it now:
employee.service.ts:
#Injectable({
providedIn: 'root'
})
export class EmployeeService {
userId: string;
constructor(public firebase: AngularFireDatabase, private datePipe: DatePipe, private afu:
AngularFireAuth, public clientService: ClientService, public contractsService: ContractsService,
public maintainerService: MaintainerService) {
this.afu.authState.subscribe(user=>{
if(user) this.userId=user.uid;
})
}
employeeList: AngularFireList<any>;
clientList: AngularFireList<any>;
maintainerList: AngularFireList<any>;
contractList: AngularFireList<any>;
array=[];
form: FormGroup=new FormGroup({
$key: new FormControl(null),
sifra: new FormControl(''),
caseName: new FormControl(''),
department: new FormControl(''),
startDate: new FormControl(new Date()),
startTime: new FormControl(''),
finishTime: new FormControl(''),
isPermanent: new FormControl(false), //nije obavezno
description: new FormControl(''),
remark: new FormControl(''), //nije obavezno
serviceType: new FormControl('1'),
isReplaceable: new FormControl(''),
maintainer: new FormControl(''),
contracts: new FormControl(''),
dnevnica: new FormControl(''),
client: new FormControl('')
});
initializeFormGroup(){
this.form.setValue({
$key: null,
sifra: '',
caseName: '',
department: '',
startDate: '',
startTime: '',
finishTime: '',
isPermanent: false,
description: '',
remark: '',
serviceType: '1',
isReplaceable: '',
maintainer: '',
contracts: '',
dnevnica: '',
client: ''
});
}
getEmployees(){
this.employeeList=this.firebase.list(`employees/${this.userId}`);
return this.employeeList.snapshotChanges();
}
And in my compoent file:
ngOnInit(): void {
this.service.getEmployees().subscribe(
list=>{
let array = list.map(item=>{
let clientName=this.clientService.getClientName(item.payload.val()['client']);
let maintainerName=this.maintainerService.getMaintainerName(item.payload.val()['maintainer']);
return{
$key: item.key,
clientName,
maintainerName,
...item.payload.val()
};
});
this.listData= new MatTableDataSource(array);
this.listData.sort=this.sort;
this.listData.paginator=this.paginator;
this.listData.filterPredicate=(data, filter)=>{
return this.displayColumns.some(ele=>{
return ele != 'actions' && data[ele].toLowerCase().indexOf(filter) != -1;
});
}
});
}
When I login for the first time, everything is good. When I refresh page, all my keep disappearing!
It's pretty strange, since my data is still in my database but if I click back button on my browser and enter my component again, data is there again!
Thanks in advance.
That is because onAuthStatusChanged(), which is what authState proxies, returns a trinary value, not binary.
Since you're using a truthy check to determine if the user is authenticated, you've created a race condition because you're not waiting for the SDK to fully initialize.
constructor(private afu: AngularFireAuth) {
this.afu.authState.subscribe(user=>{
if(user) this.userId=user.uid;
})
}
Since Firebase Auth is asynchronous, the value returned from authState or onAuthStatusChanged can be one of three values:
undefined: The JS SDK has initialized but hasn't checked the user's authentication status yet.
null: The user is unauthenticated.
User Object: The user is authenticated.
What you need to do is wait until authState returns either null or User like this:
enum AuthState {
UNKNOWN,
UNAUTHENTICATED,
AUTHENTICATED
}
// This subject will store the user's current auth state
private _state = new BehaviorSubject<AuthState>(AuthState.UNKNOWN);
constructor(private afu: AngularFireAuth) {
this.afu.authState.subscribe(user=>{
if (typeof user === 'undefined') {
// Do nothing because the user's auth state is unknown
return;
} else if (user === null) {
// User is unauthenticated
this._state.next(AuthState.UNAUTHENTICATED);
} else {
// User is authenticated
this.userId = user.uid;
this._state.next(AuthState.AUTHENTICATED);
}
})
}
// Public method to monitor user's auth state
public state$(): Observable {
return this._state.asObservable();
}
Then in your component you need to subscribe to the state$() observable before calling getEmployees().
ngOnInit(): void {
this.service.state$().subscribe((state: AuthState) => {
// We don't know what the user's auth state is, so exit waiting for an update
if (state === AuthState.UNKNOWN) {
return;
} else if (state === AuthState.UNAUTHENTICATED) {
// User is unauthenticated so redirect to login or whatever
} else {
// User is authenticated, so now we can call getEmployees()
this.service.getEmployees().subscribe(...);
}
});
}

how i get all items of all users

I'm practicing some Angular/Ionic and am having a bit of a hard time figuring out how i get all offresList of all users
this is my database look like :
This is my providre offre.ts
export class OffreProvider {
public offreListRef: firebase.database.Reference;
constructor() {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.offreListRef = firebase
.database()
.ref(`/userProfile/${user.uid}/offreList`);
}
});
}
createOffre(
offreTitre: string,
offreSecteur: string,
offreVille: string,
offreDispo: string,
offreDescrip: string,
offreDate : string,
): firebase.database.ThenableReference {
return this.offreListRef.push({
titre: offreTitre,
secteur: offreSecteur,
ville: offreVille,
dispo: offreDispo,
descrip: offreDescrip,
date : offreDate
});
}
getOffreList(): firebase.database.Reference {
return this.offreListRef;
}
}
and this is how i get all offres of currentUser
mesOffres.ts
export class MesOffresPage {
public offreList: Array<any>;
constructor(public navCtrl: NavController, public navParams: NavParams,
public offreProvider: OffreProvider) {
}
creatOffre(): void {
this.navCtrl.push('CreateOffrePage');
}
ionViewDidLoad() {
this.offreProvider.getOffreList().on("value", offreListSnapshot => {
this.offreList = [];
offreListSnapshot.forEach(snap => {
this.offreList.push({
id: snap.key,
titre: snap.val().titre,
secteur: snap.val().secteur,
ville: snap.val().ville
});
return false;
});
});
}
}
now how i can get all offreslist of all Users with alloffres.ts
and display it in alloffres.html
I m stacking for 2 days
To get the offers across all users, you will have to load all user data. Something like this:
ionViewDidLoad() {
let ref = firebase.database().ref("userProfile");
ref.on("value", userListSnapshot => {
this.offreList = [];
userListSnapshot.forEach(userSnapshot => {
let offerListSnapshot = userSnapshot.child("offreList");
offerListSnapshot.forEach(offerSnapshot => {
this.offreList.push({
id: snap.key,
titre: snap.val().titre,
secteur: snap.val().secteur,
ville: snap.val().ville
});
});
})
});
}
Note that this code also loads the profile data for each user, which the it doesn't use. This is one of the many reasons why experienced Firebase developers recommend to keep separate entity types in separate top-level lists. So in your case, I'd recommend having:
userProfiles: {
uid1: {
...
},
uid2: {
...
}
},
userOffers: {
uid1: {
"-LRZ...": {
...
}
},
uid2: {
"-LRQ...": {
...
}
}
}
With the above structure you can load just the offers for all users with code very similar to what I shared above. But with the updated structure, you won't be loading the user profile data unnecessarily. And just in case you need the profile data and offers for a user, you can easily load both in separate calls. The performance will be very similar, since Firebase pipelines the requests over a single connection.

Comparing Data in Subscribe Angular & Observable RXJS

I am new to Angular & have written below code using in-memory-web-api for Login POC,
DB-service.service:
import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
let users = [
{id: 1, username: 'user1', password:'user1', name:'John'},
{id: 2, username: 'user2', password:'user2', name:'David'},
{id: 3, username: 'user3', password:'user3', name:'Brad'},
{id: 4, username: 'user4', password:'user4', name:'Jim'},
{id: 5, username: 'user5', password:'user5', name:'Saun'}
];
return {users};
}
}
user.service:
import { loginUser } from '../_model/user';
#Injectable()
export class UserService {
private headers = new Headers({ 'Content-Type': 'application/json' });
private userUrl = 'api/users'; // URL to web api
constructor(private http: Http) {
}
getLogin(username: string, password: string) {
const url = `${this.userUrl}`;
return this.http.get(url).map(res => res.json());
}
}
model/user.ts
export class loginUser {
constructor(
public id: number,
public username: string,
public password: string,
public name: string) { }
}
login.component.ts
login(form: FormGroup) {
if (this.loginForm.valid) {
this.userData.getLogin(form.value.loginUserTxt, form.value.loginPassTxt)
.subscribe(
data => {
console.log(data);
//comparing the data from the array in DB-service.service
},
error => {
console.log("Fail");
});
}
My issue is that how can I compare that data in subscribe of login.component.ts with the input value.
I have update the code below in subscribe
this.loggedUser = this.userData.getAuthenticate(data, form.value.loginUserTxt, form.value.loginPassTxt)
if (this.loggedUser == "Invalid") {
//error
} else {
//redirect
}
Thanks all

How to implement a remember me function?

I am doing an Angular 4 application with node js backend. I did the login form, and all is good I want to implement the function "remember me".
This my login service:
import { Injectable } from '#angular/core';
#Injectable()
export class loginService{
rememberMe: boolean;
constructor() { }
login(credentials) {
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
}
getCostumer() {
const user = {
Name: sessionStorage.getItem('firstName'),
token: sessionStorage.getItem('token')
}
This is the component:
constructor(private signInService: SignInService, private router: Router,
public dialog: MatDialog, private authService: AuthService) { }
ngOnInit() { }
login(costumer) {
this.loginService.login(costumer).subscribe((data) => {
this.authService.login(data);
this.router.navigate(['home']);
this.dialog.closeAll();
}, err => {
this.message = err._body;
console.log(this.message);
});
}
}
Use localStorage instead of sessionStorage
In your case, you can do something like this:
if (isRemberMeChecked) {
...
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('token', credentials.token);
...
} else {
...
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
...
}
If you want to get isRemberMeChecked value globally you can use angular service
What you want to do here is use localStorage for the rememberMe and credentials.firstName. The credentials.token you can store in the sessionStorage:
login(credentials) {
localStorage.removeItem('Name');
localStorage.removeItem('RememberMe');
sessionStorage.setItem('token', credentials.token);
if(rememberMe){
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('RememberMe', JSON.stringify(this.rememberMe));
}
}
After a reload it will fetch the RememberMe and Name:
if(JSON.parse(localStorage.getItem('RememberMe')) !== null)
{
this.name = localStorage.getItem('Name');
this.rememberMe = JSON.parse(localStorage.getItem('RememberMe'));
}

Nativescript + Angular 2 chatService

i have a trouble.
here i let my code.
https://gist.github.com/anonymous/b651408a8419f13a949d719e6b87d8ea
in my app i connect to the firebase cloud message service, in the appComponent i listen the messages that firebise send and emit the data content whit the DataInterchage.service, in the chatComponent i suscribe to the event emited and i process the data.
the problem is the next. when I receved the data, i set the this.messeges variable the data content but the view dont update.
what do you believe that be?
when you set this.messages your code might be running outside the angular because that code is written in service callback. that is why when you assign values to variable it doesn't update the view.
try running code inside the angular NgZone. after that your view will be updated successfully.
for your code snippet will be
import {NgZone,ChangeDetectorRef} from "#angular/core";
export class ChatComponent implements OnInit{
constructor(
private zone: NgZone,
private cd: ChangeDetectorRef,
) {}
ngOnInit() {
this.user = JSON.parse(appStorage.getString("user_info"));
this.me = {
id: this.user.id,
name: this.user.full_name,
pictureUrl: this.user.icon
};
this.other = {
id: "",
name: "",
pictureUrl: "",
coverUrl: ""
};
this.emitter.msgRecived$
.subscribe(data => {
data = JSON.parse(data);
this.http.get(`${ env['api_route'] }/api/users/${ data.user }`)
.subscribe((res: Response) => {
let user = res.json().data;
this.other = {
id: user.id,
name: user.full_name,
pictureUrl: user.icon,
};
this.zone.run(()=>{
this.messages.push({
sender: this.other,
content: data.message,
date: data.date
});
});
console.dump(this.other);
console.dump(this.messages)
}, (err: Response) => {
this.oauth.isLogged(err);
});
});
}
}

Categories

Resources