@lomray/microservice-users
Version:
Users microservice based on NodeJS & inverted json.
231 lines (227 loc) • 8.49 kB
JavaScript
'use strict';
var tslib = require('tslib');
var microserviceHelpers = require('@lomray/microservice-helpers');
var microserviceNodejsLib = require('@lomray/microservice-nodejs-lib');
var firebaseSdk = require('../external/firebase-sdk.js');
var abstract = require('./abstract.js');
/**
* Firebase identity provider
*/
class Firebase extends abstract {
/**
* Return user by identity token
*/
getUserByToken() {
return tslib.__awaiter(this, void 0, void 0, function* () {
// Get firebase user
const [firebaseUser] = yield this.getFirebaseUser();
// Get related user from db
const user = yield this.userRepository.findUserByIdentifier(this.provider, firebaseUser.uid);
if (!user) {
throw new microserviceNodejsLib.BaseException({
status: 404,
message: 'User was not found.',
});
}
return user;
});
}
/**
* @inheritDoc
*/
signIn({ isDenyRegister, isDenyAuthViaRegister, isShouldAttachUserPhoto = true, isShouldApproveProvider = false, } = {}) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const [firebaseUser, providerType] = yield this.getFirebaseUser();
const user = yield this.userRepository.findUserByIdentifier(this.provider, firebaseUser.uid);
/**
* Verify if the user was deleted and can he restore the account
*/
yield this.userRepository.verifyDeleteAt(user);
this.isShouldAttachUserPhoto = isShouldAttachUserPhoto;
this.isShouldApproveProvider = isShouldApproveProvider;
if (!user) {
if (isDenyRegister) {
throw new microserviceNodejsLib.BaseException({
status: 500,
message: 'User not found.',
});
}
const userResult = yield this.register(firebaseUser, providerType);
return { user: userResult, isNew: true };
}
if (isDenyAuthViaRegister) {
/**
* If user registered - error
*/
throw new microserviceNodejsLib.BaseException({
status: 500,
message: 'User already exists.',
});
}
return { user, isNew: false };
});
}
/**
* @inheritDoc
*/
attachProvider(userId) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const [firebaseUser, providerType] = yield this.getFirebaseUser();
const user = yield this.userRepository.findOne({ id: userId }, { relations: ['profile'] });
if (!user) {
throw new microserviceNodejsLib.BaseException({
status: 404,
message: 'User not found.',
});
}
const { profile, email, phone } = user;
// @ts-ignore this need for success pass validation
delete user.profile;
if (!email && firebaseUser.email) {
user.email = firebaseUser.email;
}
if (!phone && firebaseUser.phoneNumber) {
user.phone = firebaseUser.phoneNumber;
}
const identityProvider = this.getIdentityProvider(firebaseUser, providerType);
return this.assign(identityProvider, user, this.getProfile(firebaseUser, profile));
});
}
/**
* Sign up user
* NOTE: type - (google or facebook)
* @protected
*/
register(firebaseUser, type) {
var _a, _b;
const [firstName, lastName, middleName] = (_b = (_a = firebaseUser.displayName) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : [];
const user = this.userRepository.create({
firstName,
lastName,
middleName,
email: firebaseUser.email,
phone: firebaseUser.phoneNumber,
});
const profile = this.getProfile(firebaseUser);
const identityProvider = this.getIdentityProvider(firebaseUser, type);
/**
* Approve non-trusted identity provider
*/
void this.approveFirebaseUserProvider(firebaseUser);
return this.createUser(user, identityProvider, profile);
}
/**
* Approve firebase user identity
* NOTE: Set emailVerified to true for preventing override
* non-trusted providers
*/
approveFirebaseUserProvider(firebaseUser) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const firebase = yield firebaseSdk();
/**
* If email verified by default true for trusted provider
*/
if (firebaseUser.emailVerified || !this.isShouldApproveProvider) {
return;
}
yield firebase.auth().updateUser(firebaseUser.uid, {
emailVerified: true,
});
});
}
/**
* Returns user photo if it should be attached
* NOTE: Uses while user on split sign up want to upload own photo,
* in this case we don't need to set photo from user provider result
*/
getUserPhoto(firebaseUser) {
var _a;
if (!this.isShouldAttachUserPhoto) {
return null;
}
return (_a = Firebase.getUserPhoto(firebaseUser)) !== null && _a !== void 0 ? _a : null;
}
/**
* Make or update user profile
* @protected
*/
getProfile(firebaseUser, profile) {
const updatedProfile = profile !== null && profile !== void 0 ? profile : this.profileRepository.create({ params: {} });
if (!updatedProfile.photo) {
updatedProfile.photo = this.getUserPhoto(firebaseUser);
}
updatedProfile.params.isEmailVerified = firebaseUser.emailVerified;
updatedProfile.params.isPhoneVerified = Boolean(firebaseUser.phoneNumber);
return updatedProfile;
}
/**
* Get current identity provider
* @protected
*/
getIdentityProvider(firebaseUser, type) {
return this.providerRepository.create({
provider: this.provider,
identifier: firebaseUser.uid,
type,
params: {
uid: Firebase.getTypeUid(firebaseUser, type),
},
});
}
/**
* Get provider uid for facebook, google, etc...
* @protected
*/
static getTypeUid(firebaseUser, type) {
for (const { providerId, uid } of firebaseUser.providerData) {
if (providerId === type) {
return uid;
}
}
return undefined;
}
/**
* Get firebase user photo with large size
* @protected
*/
static getUserPhoto(firebaseUser) {
for (const { providerId, photoURL } of firebaseUser.providerData) {
if (providerId.includes('google')) {
return photoURL === null || photoURL === void 0 ? void 0 : photoURL.replace('s96-c', 's400-c');
}
else if (providerId.includes('facebook')) {
return `${photoURL}?type=large`;
}
}
return firebaseUser.photoURL;
}
/**
* Get firebase user by token
* @protected
*/
getFirebaseUser() {
return tslib.__awaiter(this, void 0, void 0, function* () {
const firebase = yield firebaseSdk();
try {
const validToken = yield firebase.auth().verifyIdToken(this.token);
const identifier = validToken.sub;
const firebaseUser = yield firebase.auth().getUser(identifier);
if (firebaseUser.disabled) {
throw new Error('User disabled.');
}
return [firebaseUser, validToken.firebase.sign_in_provider];
}
catch (e) {
microserviceHelpers.Log.error('Failed verify firebase token', e);
throw new microserviceNodejsLib.BaseException({
status: 422,
message: 'Bad firebase token.',
payload: {
original: e.message,
},
});
}
});
}
}
module.exports = Firebase;