由于我已经挣扎了一段时间,所以无法弄清楚以下情况:
我有一个组件“ test.ts”和一个服务“ authService”。 在组件的ngOnInit方法中,我订阅了服务的authState。效果很好。
我要实现的目标如下: 如果用户已通过身份验证,我想从Firebase数据库加载配置文件数据。然后,此Firebase数据将作为配置文件对象分配给服务的私有成员变量。
userprofile: Userprofile = null; // This is a class member
let fbUserProfile: Observable<any> = this.afDatabase.object(`${this.PATH_USER_PROFILE}/${userID}`).valueChanges();
this.userprofile = this.currentUserProfile( fbUserProfile );
authService中的私有方法currentUserProfile将创建一个新的Userprofile对象,并从给定的Observable中分配值。
并行,我想获取该用户的分配凭据列表,并将其存储到服务的私有成员变量中。
usercredentials: Map<string, Credential> = null; // This is a class member
let fbUsercredentials: Observable<any> = this.afDatabase.list<Credential>(`${this.PATH_USER_CREDENTIALS}/${userID}`).snapshotChanges().pipe(
map(changes => changes.map(c => ({ key: c.payload.key, ...c.payload.val() }) ))
);
this.usercredentials = this.currentAssignedUserCredentials( fbUsercredentials )
注意:用户没有任何凭证是有效的! 在currentAssignedUserCredentials函数中,我订阅了给定的observable并构建了地图。
这是我目前无法确定的事情: 我想在服务中订阅authState,因此我希望两个成员变量都被填充。 像这样:
this.authService.authstate$.subscribe( () => {
this.authServive.getUserprofile(); // should return a Userprofile object that is filled with the firebase information
this.authService.getUsercredentials(); // should return the map with assigned user credentials (or null)
}
这是我的auth.service.ts文件的样子:
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import {AngularFireAuth} from '@angular/fire/auth';
import {AngularFireDatabase, AngularFireObject, AngularFireList} from '@angular/fire/database';
import { Credential } from '../items/credentials.model';
import { Userprofile } from '../items/userprofile.model';
import { Observable, of} from 'rxjs';
import { switchMap, filter, map } from 'rxjs/operators';
import { Constants } from '../core/constants.model';
@Injectable({
providedIn: 'root'
})
export class AuthService {
public authstate$: Observable<any | null>;
private readonly PATH_USER_PROFILE = 'users/userprofiles';
private readonly PATH_CREDENTIALS = 'credentials';
private readonly PATH_USER_CREDENTIALS = 'credentials/users';
private firebaseUser: firebase.User = null; // the firebase informations if the user is logged in
private userprofile: Userprofile = null;
private credentialno = 'Demo';
private usercredential: Credential = this.updateUserCredential(null);
private assignedUserCredentials$: Observable<any | null>;
private credentialMap: Map<string, Credential>;
constructor(private afAuth: AngularFireAuth,
private afDatabase: AngularFireDatabase,
private router: Router) {
this.authstate$ = this.afAuth.authState.pipe(
filter(fbUser => fbUser !== null),
switchMap( (fbUser: firebase.User) => {
if (fbUser) {
// The user is logged in successfully.
this.firebaseUser = fbUser;
// return the userprofile observable depending from his user id
let fbUserprofileObject = this.getUserprofileObjectById(this.firebaseUser.uid);
return fbUserprofileObject.valueChanges();
} else {
// The user isn't logged in
this.firebaseUser = null;
return of(null);
}
}),
switchMap( (fbUserprofile) => {
if (fbUserprofile) {
// create the userprofile
this.userprofile = this.currentUserProfile( fbUserprofile );
return of( this.userprofile.getUid() );
} else {
return of(null);
}
} ),
switchMap( (userID: string) => {
if (userID) {
let fbAssignedUserCredentials: AngularFireList<any> = this.getUserCredentialListById(userID);
this.assignedUserCredentials$ = fbAssignedUserCredentials.snapshotChanges().pipe(
map(changes => changes.map(c => ({ key: c.payload.key, ...c.payload.val() }) ))
);
this.credentialMap = this.currentAssignedUserCredentials(this.assignedUserCredentials$);
return of(null);
} else {
// FV: Add a demo credential to the usercredentiallist
//this.credentialMap.set('Demo', new Credential('Demo', 1, '', 0));
return of(null);
}
})
);
}
// #######################
// ## GETTER AND SETTER ##
// #######################
get authenticated(): boolean {
// Returns true if user is logged in
return this.firebaseUser !== null;
}
get currentUserId(): string {
// Returns current user UID or empty string
return this.authenticated ? this.firebaseUser.uid : '';
}
get currentUserEmail(): string {
// Returns current user email address or empty string
return this.firebaseUser ? this.firebaseUser.email : '';
}
get currentUserEmailVerified(): boolean {
// Retruns true if the email address is verfified or false
return this.authenticated ? this.firebaseUser.emailVerified : false;
}
get currentUserAnonymous(): boolean {
// Returns true if this user is an anonymous user
return this.authenticated ? this.firebaseUser.isAnonymous : false;
}
get currentUserDisplayName(): string {
// Returns current user display name or Guest
if (!this.firebaseUser) { return 'Guest'; }
if (this.currentUserAnonymous) {
return 'Anonymous';
} else {
return this.firebaseUser['displayName'] || 'User without a Name';
}
}
get FirebaseLoginMethod(): number {
// Returns the Firebase login method as number
let retrunValue: number = Constants.LOGIN_OPTION_NOT_LOGGED_IN;
if (this.authenticated) {
switch (this.firebaseUser.providerId) {
case 'facebook.com': {
// For linked facebook account
retrunValue = Constants.LOGIN_OPTION_FACEBOOK;
break;
}
case 'google.com': {
// For linked Google account
retrunValue = Constants.LOGIN_OPTION_GOOGLE;
break;
}
case 'password': {
// For Email/Password account
retrunValue = Constants.LOGIN_OPTION_PASSWORD;
break;
}
default: {
retrunValue = Constants.LOGIN_OPTION_UNKNOWN;
}
}
}
return retrunValue;
}
// ####################
// ## PUBLIC METHODS ##
// ####################
public getUserProfile(): Userprofile {
console.log('getUserProfile - start');
return this.currentUserProfile(null);
}
public getAssignedUserCredentials(): Map<string, Credential> {
return this.currentAssignedUserCredentials(null);
}
public getUserCredential(): Credential {
return this.usercredential;
}
public setUserCredential(newCredential: Credential): void {
this.usercredential = newCredential;
}
public setUserProfile(newProfile: Userprofile): void {
this.userprofile = newProfile;
}
public signOut() {
this.afAuth.auth.signOut().then(() => {
this.firebaseUser = null;
this.authstate$ = null;
this.userprofile = null;
this.credentialno = 'Demo';
this.usercredential = this.updateUserCredential(null);
this.router.navigate(['home']);
});
}
public updateFBUserProfile() {
const fbUserprofileObject = this.getUserprofileObjectById(this.userprofile.getUid());
return fbUserprofileObject.update({
fullname: this.userprofile.getFullname() as String,
email: this.userprofile.getEmail() as String,
phone: this.userprofile.getPhone() as String,
postaladdress: this.userprofile.getAddress() as String,
serialnumber: this.usercredential.getSerialnumber() as String
});
}
public updateFBUserCredential() {
const fbUsercrednetialObject = this.getUserCredentialObjectById(this.usercredential.getSerialnumber());
return fbUsercrednetialObject.update({
accesslevel: this.usercredential.getAccesslevel() as Number,
assigneduserprofile: this.usercredential.getAssignedUserprofile() as String,
validuntil: this.usercredential.getValidUntil() as Number
});
}
// ############################
// ## PRIVATE HELPER METHODS ##
// ############################
private currentUserProfile(fbUserprofile: Observable<any>): Userprofile {
console.log('currentUserProfile - start');
let profile_new: Userprofile = null;
let photourl = '';
// if the userprofile is already build then return it
if (this.userprofile) {
console.log('9');
return this.userprofile;
}
console.log('9.1');
profile_new = new Userprofile('', '', false, '', '', '', '', 10);
// if the user is authenticated then fill the new profile with that information
if (this.authenticated) {
profile_new.setUid(this.currentUserId);
profile_new.setEmail(this.currentUserEmail);
profile_new.setEmailVerified(this.currentUserEmailVerified);
profile_new.setFullname(this.currentUserDisplayName);
// photourl
this.firebaseUser.providerData.forEach(profil => {
photourl = profil.photoURL;
});
// photourl - the image url in firebase auth user must be corrected
profile_new.setPhotoUrl(this.updatePhotoUrl(photourl));
profile_new.setLoginMethod(this.FirebaseLoginMethod);
}
// if the fbUserprofile isn't null then get the data from there
if (fbUserprofile) {
// Fullname
if (fbUserprofile.fullname.length > 0) { profile_new.setFullname(fbUserprofile.fullname); }
// phone
profile_new.setPhone(fbUserprofile.phone);
// postal address
profile_new.setAddress(fbUserprofile.postaladdress);
// Get Credentials assigned to the user
this.credentialno = fbUserprofile.serialnumber;
}
console.log('currentUserProfile - stop');
// return the new profile
return profile_new;
}
private updatePhotoUrl(photourl: string): string {
let returnValue = photourl;
// If the main profile Pic is an expiring facebook profile pic URL we'll update it automatically
// to use the permanent graph API URL.
if (returnValue && (returnValue.indexOf('lookaside.facebook.com') !== -1 || returnValue.indexOf('fbcdn.net') !== -1)) {
// Fid the user's Facebook UID.
const facebookUID = this.firebaseUser.providerData.find((providerData) => providerData.providerId === 'facebook.com').uid;
returnValue = `https://graph.facebook.com/${facebookUID}/picture?type=small`;
this.firebaseUser.updateProfile({displayName: this.firebaseUser.displayName, photoURL: returnValue}).then(() => {
// console.log('User profile photourl updated.');
});
}
return returnValue;
}
public updateUserCredential(fbCredential: any): Credential {
let credential_new: Credential;
if (fbCredential) {
credential_new = new Credential(this.credentialno, fbCredential.accesslevel,
fbCredential.assigneduserprofile, fbCredential.validuntil);
} else {
credential_new = new Credential('Demo', 1, '', 0);
}
return credential_new;
}
private getUserprofileObjectById(userID: string): AngularFireObject<any> {
return this.afDatabase.object(`${this.PATH_USER_PROFILE}/${userID}`);
}
public getUserCredentialObjectById(credentialID: string): AngularFireObject<any> {
return this.afDatabase.object(`${this.PATH_CREDENTIALS}/${credentialID}`);
}
public getUserCredentialListById(userID: string): AngularFireList<any> {
return this.afDatabase.list<Credential>(`${this.PATH_USER_CREDENTIALS}/${userID}`);
}
private currentAssignedUserCredentials(assignedUserCredentials$: Observable<any | null>): Map<string, Credential> {
let mocked_usercredentials: Map<string, Credential> = null;
// if the assigned user credentials are already build then return it
if (this.credentialMap) {
return this.credentialMap;
}
mocked_usercredentials = new Map();
if(assignedUserCredentials$) {
assignedUserCredentials$.subscribe(credentials => {
credentials.map(item => {
mocked_usercredentials.set(item.key, new Credential(item.key, item.accesslevel, this.userprofile.getUid(), item.validuntil));
});
return mocked_usercredentials;
});
} else {
return null;
}
}
}
感谢您的帮助! 问候弗兰克