File

modules/firebase-connector/src/firebase-connector.ts

Description

Service that realize logic with connecting to firebase realtime database and authentication.
Components user doesn't directly calls connector method. He calls them from DAL

Querying to Firebase Realtime Database are executed with Firebase Flashlight.
If you want to create you own connector you must adopt it to ElasticSearch flashlight output.

Constructor

constructor(http: any)

Methods

connectSessionFlowToDB
connectSessionFlowToDB(sessionFlow: any, deviceId: any, sessionId: any)

Connect Session-flow to databese.

Parameters :
  • sessionFlow : SessionFlow

    SessionFlow service

  • deviceId

    User device id generated by SessionFlow

  • sessionId

    User session id generated by SessionFlow

Returns: void
Private listenSfObject
listenSfObject(sf: any)

Subscribes to user visited routes and clicks

Parameters :
Returns: void
getFirebase
getFirebase()

Returns firebase object. Avoid manipulating with connector directly. Use dal methods to communicate with connector

Returns: void

Firebase object

getFirebaseDB
getFirebaseDB()

Returns firebase realtime database object. Avoid manipulating with connector directly. Use dal methods to communicate with connector

Returns: void

Firebase realtime database object

getAuth
getAuth()

Returns firebase auth object. Avoid manipulating with connector directly. Use dal methods to communicate with connector

Returns: void

Firebase auth object

register
register(email: any, password: any)

Register user with email and password

Parameters :
  • email

    User email

  • password

    User password

Returns: void

[firebase.Promise]{

registerUser
registerUser(registerForm: any)

Register user with email and password. Save additional information in database

Parameters :
  • registerForm

    Object that have email, password and any additional information about user.
    Additional information stores in firebase as user backet

Returns: any
Private guid
guid()

Generate guid for user Id

Returns: void

guid

loginEmail
loginEmail(email: any, password: any)

Login with email and password

Parameters :
  • email

    User email

  • password

    User password

Returns: void

Observable containing non-null [firebase.User]{

getUserData
getUserData(uid: any)

Get user data

Parameters :
  • uid

    user Id

Returns: void

[firebase.database.Reference]{

logout
logout()

Logout user from firebase

Returns: void
checkOldSessionFlow
checkOldSessionFlow(deviceId: any)

Check old session flow using device id

Parameters :
  • deviceId

    User device Id

Returns: void
getBasketContent
getBasketContent(userId: any)

Returns basket content of specific user

Parameters :
  • userId

    user Id

Returns: void

Observable of basket

getComparison
getComparison(id: any)

Will be realized in next versions

Returns: void
initializeBasketHistory
initializeBasketHistory(userId: any)

Initialize basket history for user. If you want to track basket history run this method when user sign in

Parameters :
  • userId

    userId or deviceId

Returns: void
getBasketHistorySubject
getBasketHistorySubject()

Returns basket history subject

Returns: any

basketHistory Subject of basketHistory

getBasketHistoryById
getBasketHistoryById(userId: any)

Returns Rx Observable of basket history of user by userId or deviceId

Parameters :
  • userId

    userId or deviceId

Returns: void

Rx Observable of basket history

setNewBasket
setNewBasket(id: any, newBasket: any)

Set new basket by user id or device id

Parameters :
  • id

    userId or deviceId

  • newBasket
Returns: void

Observable of basket

addProductToComparison
addProductToComparison(id: any, product: any)

Will be realized in next versions

Returns: void
removeProductFromComparison
removeProductFromComparison(id: any, idInComparison: any)

Will be realized in next versions

Returns: void
requestData
requestData(index: any, type: any, body: any)

Gets data hits from firebase using flashlight lib for ElasticSearch

Parameters :
  • index

    ElasticSearch index

  • type

    ElasticSearch type

  • body : Object

    query object for ElasticSearch

Returns: void

Observable of requested data hits

requestFullData
requestFullData(index: any, type: any, body: any)

Gets full data from firebase using flashlight lib for ElasticSearch

Parameters :
  • index

    ElasticSearch index

  • type

    ElasticSearch type

  • body : Object

    query object for ElasticSearch

Returns: void

Observable of requested data

requestItemsTotal
requestItemsTotal(index: any, type: any, body: any)

Gets total item of data from firebase using flashlight lib for ElasticSearch

Parameters :
  • index

    ElasticSearch index

  • type

    ElasticSearch type

  • body : Object

    query object for ElasticSearch

Returns: void

Observable of total item

addProduct
addProduct(product: any)

Add product to database

Parameters :
  • product : Object

    product Object

Returns: void
getVisitedRoutes
getVisitedRoutes()

Returns visited routes

Returns: void

array of visited routes objects

getUserClicks
getUserClicks()

Returns user clicks

Returns: void

array of user clicks objects

addGeneralCategory
addGeneralCategory(generalCategoryForm: any)

Add general category to database

Parameters :
  • generalCategoryForm : FormGroup

    form of general category

Returns: void
addCategory
addCategory(categoryForm: any)

Add category to database

Parameters :
Returns: void
addAttribute
addAttribute(attributeForm: any, categoryId: any)

Add new attribute to database

Parameters :
  • attributeForm : FormGroup

    form of attribute

  • categoryId

    id of category

Returns: void
addTag
addTag(tagForm: any, categoryId: any)

Add new tag to database

Parameters :
  • tagForm : FormGroup

    form of tag

  • categoryId

    id of category

Returns: void
saveOrder
saveOrder(paymentData: any)

Save new order to database

Parameters :
  • paymentData : Object
Returns: void

Observable of orders

addPaymentRequest
addPaymentRequest(data: any, paymentMethod: any)

Add payment requets. Server listens firebase backet with payments request and process coming requests

Parameters :
  • data : Object

    PaymentData

  • paymentMethod

    name of payment method

Returns: void

[firebase.database.ThenableReference]{

listenPaymentResponse
listenPaymentResponse(paymentKey: any)

Returns payment response by id

Parameters :
  • paymentKey

    id of payment response. Payment request and payment response have same ids in their backets

Returns: void

Observable of payment response

resetPassword
resetPassword(email: any)

Send letter with password resetting to specific email

Parameters :
  • email

    User email

Returns: void

[firebase.Promise]{

getOrderById
getOrderById(id: any)

Get order by Id

Parameters :
  • id

    id of order

Returns: void

Observable of order

listenOrders
listenOrders()

Emits order object when new order added

Returns: any

Observable of new order

getOrderSubject
getOrderSubject()
Returns: void
getSeoText
getSeoText(url: string, indexBlock: number)
Returns: any

Properties

Private auth
auth: any
Private basketHistory$
basketHistory$: any
Private basketHistorySubscription$
basketHistorySubscription$: any
Private database
database: any
Private orderSubject
orderSubject: any
Private sfUserClicks
sfUserClicks: any

User performed clicks

Private sfVisitedRoutes
sfVisitedRoutes: any

User visited router

import { Http, Response } from '@angular/http';
import { esIndex } from './consts';
import {Injectable, Inject} from "@angular/core";
import * as firebase from 'firebase';
import {} from 'firebase';
import { Observable } from "rxjs/Observable";
import { FormGroup } from '@angular/forms';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Rx';
/**
 * Service that realize logic with connecting to firebase realtime database and authentication.
 * Components user doesn't directly calls connector method. He calls them from [DAL]{@link https://www.npmjs.com/package/@nodeart/dal}
 *
 * Querying to `Firebase Realtime Database` are executed with [Firebase Flashlight]{@link https://github.com/firebase/flashlight}.
 * If you want to create you own connector you must adopt it to `ElasticSearch flashlight` output.
 */
@Injectable()
export class FirebaseConnector {

  /**
   * User visited router
   */
  private sfVisitedRoutes;
  
  /**
   * User performed clicks
   */
  private sfUserClicks;

  private basketHistory$: Subject<any> = new Subject();

  private basketHistorySubscription$: Subscription;

  private orderSubject: Subject<any> = new Subject();

  private database  = firebase.database();

  private auth = firebase.auth();

  constructor(private http: Http){
  }

  /**
   * Connect [Session-flow]{@link https://www.npmjs.com/package/@nodeart/session-flow} to databese. 
   * 
   * @param {SessionFlow} sessionFlow  SessionFlow service
   * @param {string} deviceId  User device id generated by SessionFlow 
   * @param {string} sessionId  User session id generated by SessionFlow
   * 
   */
  connectSessionFlowToDB(sessionFlow, deviceId, sessionId) {
    this.sfVisitedRoutes = this.database
      .ref('/session-flows/' + deviceId + '/' + sessionId + '/visitedRoutes');
    this.sfUserClicks = this.database
      .ref('/session-flows/' + deviceId + '/' + sessionId + '/userClicks');  
    this.listenSfObject(sessionFlow);
  }

  /**
   * Subscribes to user visited routes and clicks
   * 
   * @param {SessionFlow} sf  SessionFlow service
   */
  private listenSfObject(sf) {
    sf.visitedRoute.subscribe((value) => {
      this.sfVisitedRoutes.push(value.getStringObject()); 
    });

    sf.click.asObservable().subscribe((value) => {
      this.sfUserClicks.push(value.getStringObject());
    });
  }


  /**
   * Returns firebase object. Avoid manipulating with connector directly. Use dal methods to communicate with connector 
   * 
   * @returns Firebase object
   */
  getFirebase(){
    return firebase;
  };

  /**
   * Returns firebase realtime database object. Avoid manipulating with connector directly. Use dal methods to communicate with connector
   * 
   * @returns Firebase realtime database object
   */
  getFirebaseDB(){
    return this.database;
  }

  /**
   * Returns firebase auth object. Avoid manipulating with connector directly. Use dal methods to communicate with connector
   * 
   * @returns Firebase auth object
   */
  getAuth(){
    return this.auth;
  }

  /**
   * Register user with email and password
   * 
   * @param {string} email  User email
   * @param {string} password  User password
   * 
   * @returns [firebase.Promise]{@link https://firebase.google.com/docs/reference/js/firebase.Promise} containing non-null [firebase.User]{@link https://firebase.google.com/docs/reference/js/firebase.User}
   */
  register(email, password){
    return this.auth.createUserWithEmailAndPassword(email, password);
  }

  /**
   * Register user with email and password. Save additional information in database
   * 
   * @param registerForm  Object that have email, password and any additional information about user. 
   * Additional information stores in firebase as user backet
   */
  registerUser(registerForm) : Observable<any>{
    let email = registerForm.email;
    let password = registerForm.password;
    delete registerForm.password;
    let userId = this.guid();
    // add current time
    registerForm["registerTime"] = Date.now();
    return Observable.create(observer => {
      this.register(email, password).then(authData => {
        let uid = authData.uid;
        registerForm.uid = uid;
        this.database.ref('user/' + userId).set(registerForm).then(data => {
           this.loginEmail(email, password).subscribe( 
            data => {
              observer.next(data);
              observer.complete();
            },
            error => {
                observer.error(error);
            });
        });
      }).catch( error => {
        observer.error(error);
      });
    });
  }

  /**
   * Generate guid for user Id
   * 
   * @returns guid
   */
  private guid() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
  }

  /**
   * Login with email and password
   * 
   * @param {string} email  User email
   * @param {string} password  User password
   * 
   * @returns {Observable} Observable containing non-null [firebase.User]{@link https://firebase.google.com/docs/reference/js/firebase.User}
   */ 
  loginEmail(email, password){
    return Observable.create( observer => {
      this.auth.signInWithEmailAndPassword(email, password)
        .then(data => {
          observer.next(data);
          observer.complete();
        })
        .catch(error => {
          observer.error(error);
          observer.complete();
        });
    });
  }

  /**
   * Get user data
   * 
   * @param {string} uid  user Id
   * 
   * @returns [firebase.database.Reference]{@link https://firebase.google.com/docs/reference/js/firebase.database.Reference}
   */ 
  getUserData(uid){
    let queryObj = {
      query: {
        match: {
          "uid" : uid
        }
      }
    };
    return this.requestData(esIndex, 'user', queryObj);
  }

  /**
   * Logout user from firebase
   */
  logout(){
    this.auth.signOut();
  }

  /**
   * Check old session flow using device id
   * 
   * @param {string} deviceId  User device Id
   */
  checkOldSessionFlow(deviceId){
    if(localStorage.getItem("oldSessionFlow")){
      let oldSessionFlow = JSON.parse(localStorage.getItem("oldSessionFlow"));
      let sessionId = oldSessionFlow.sessionId;
      delete oldSessionFlow.sessionId;
      this.database.ref('/session-flows/' + deviceId + '/' + sessionId).set(oldSessionFlow);
    }
  }

  /**
   * Returns basket content of specific user
   * 
   * @param {string} userId user Id
   * 
   * @returns {Observable} Observable of basket
   */
  getBasketContent(userId){
    return Observable.create( observer => {
      this.database.ref().child('/basket/' + userId).on('value', data => {
        observer.next(data);
      });
    });
  }

  /**
   * Will be realized in next versions
   */
  getComparison(id){
    return this.database.ref().child('comparison/' + id).once('value');
  }

  /**
   * Initialize basket history for user. If you want to track basket history run this method when user sign in
   * 
   * @param {string} userId userId or deviceId
   * 
   */
  initializeBasketHistory(userId) {
    if(this.basketHistorySubscription$){
      this.basketHistorySubscription$.unsubscribe();
    }
    this.basketHistorySubscription$ = this.basketHistory$.subscribe( data => {
      this.database.ref('/basket-history/' + userId).push(data);
    });
  }

  /**
   * Returns basket history subject
   * 
   * @returns {Subject} basketHistory Subject of basketHistory
   */
  getBasketHistorySubject(): Subject<any> {
    return this.basketHistory$;
  }

  /**
   * Returns Rx Observable of basket history of user by userId or deviceId
   * 
   * @param {string} userId  userId or deviceId
   * 
   * @returns {Observable} Rx Observable of basket history
   */
   getBasketHistoryById(userId){
     return Observable.fromPromise( 
       this.database.ref().child('/basket-history/' + userId).once('value') as Promise<any>
     );
   }


  /**
   * Set new basket by user id or device id
   * @param id  userId or deviceId
   * @param newBasket 
   * 
   * @returns {Observable} Observable of basket
   */
  setNewBasket(id, newBasket){
    return Observable.create( observer => {
        this.database.ref().child('basket/' + id).set(newBasket).then( data => {
          observer.next(data);
          observer.complete();
        });
    });
  }

  /**
   * Will be realized in next versions
   */
  addProductToComparison(id, product){
    return this.database.ref().child('comparison/' + id).push(product);
  }

  /**
   * Will be realized in next versions
   */
  removeProductFromComparison(id, idInComparison){
    return this.database.ref().child('comparison/' + id + '/' + idInComparison).remove();
  }

  /**
   * Gets data hits from firebase using [flashlight]{@link https://github.com/firebase/flashlight} lib for ElasticSearch
   * 
   * @param {string} index ElasticSearch index
   * @param {string} type ElasticSearch type
   * @param {Object} body query object for ElasticSearch
   * 
   * @returns  {Observable} Observable of requested data hits
   */
  requestData(index, type, body) {
    const key = this.database
      .ref('search/request')
      .push({ index, type, body })
      .key;
    return Observable.fromPromise(
      this.database.ref(`search/response/${key}/hits/hits`).once('child_added') as Promise<any>
    );
  }

  /**
   * Gets full data from firebase using [flashlight]{@link https://github.com/firebase/flashlight} lib for ElasticSearch
   * 
   * @param {string} index ElasticSearch index
   * @param {string} type ElasticSearch type
   * @param {Object} body query object for ElasticSearch
   * 
   * @returns  {Observable} Observable of requested data
   */
  requestFullData(index, type, body){
    const key = this.database
      .ref('search/request')
      .push({ index, type, body })
      .key;
    return Observable.fromPromise(
      this.database.ref(`search/response/${key}/hits`).once('child_added') as Promise<any>
    );
  }

  /**
   * Gets total item of data from firebase using [flashlight]{@link https://github.com/firebase/flashlight} lib for ElasticSearch
   * 
   * @param {string} index ElasticSearch index
   * @param {string} type ElasticSearch type
   * @param {Object} body query object for ElasticSearch
   * 
   * @returns  {Observable} Observable of total item
   */
  requestItemsTotal(index, type, body){
    const key = this.database
      .ref('search/request')
      .push({ index, type, body })
      .key;
    console.log(key);
    return Observable.create( observer => {
      const ref = this.database.ref(`search/response/${key}/hits/total`);
      let promise = new Promise( (resolve, reject) => {
        ref.on('value', ( data ) => {
          if(data.val() !== null){
            resolve(data);
          }
        });
      });
      promise.then( data => {
        ref.off('value');
        observer.next(data);
        observer.complete();
      });
    });
  }

  /**
   * Add product to database
   * 
   * @param {Object} product product Object
   */
  addProduct(product){
    this.database.ref('product/').push(product);
  }

  /**
   * Returns visited routes
   * 
   * @returns array of visited routes objects
   */
  getVisitedRoutes(){
    return this.sfVisitedRoutes;
  }

  /**
   * Returns user clicks 
   * 
   * @returns array of user clicks objects
   */
  getUserClicks(){
    return this.sfUserClicks;
  }

  /**
   * Add general category to database
   * 
   * @param {FormGroup} generalCategoryForm form of general category
   */
  addGeneralCategory(generalCategoryForm: FormGroup){
    this.database.ref('general-category').push(generalCategoryForm.value);
  }

  /**
   * Add category to database
   * 
   * @param {FormGroup} categoryForm  form of category
   */
  addCategory(categoryForm : FormGroup){
    this.database.ref('category/').push(categoryForm.value);
  }


  /**
   * Add new attribute to database
   * 
   * @param {FormGroup} attributeForm  form of attribute
   * @param {string} categoryId id of category
   */
  addAttribute(attributeForm : FormGroup, categoryId){
    this.database.ref('attributes/').push(attributeForm.value).then(ref => {
      this.database.ref().child('category/' + categoryId +'/attrs').once('value').then(data => {
          if(data.val()){
            console.log(data);
            if(data.val()[0] == '1234' && data.val()[1] == '1234'){
              let attrs = ['1234'];
              attrs.push(ref['key']);
              console.log(attrs);
              this.database.ref().child('category/' + categoryId + '/attrs').set(attrs);
            } else {
              let attrs = [].concat(...data.val());
              console.log(attrs);
              attrs.push(ref['key']);
              console.log(attrs);
              this.database.ref().child('category/' + categoryId + '/attrs').set(attrs);
            }
          }
      });
    });
  }

  /**
   * Add new tag to database
   * 
   * @param {FormGroup} tagForm  form of tag
   * @param {string} categoryId id of category
   */
  addTag(tagForm: FormGroup, categoryId){
    this.database.ref('tags/').push(tagForm.value).then(ref => {
      this.database.ref().child('category/' + categoryId +'/tags').once('value').then(data => {
          if(data.val()){
            console.log(data);
            if(data.val()[0] == '1234' && data.val()[1] == '1234'){
              let tags = ['1234'];
              tags.push(ref['key']);
              console.log(tags);
              this.database.ref().child('category/' + categoryId + '/tags').set(tags);
            } else {
              let tags = [].concat(data.val());
              tags.push(ref['key']);
              console.log(tags);
              this.database.ref().child('category/' + categoryId + '/tags').set(tags);
            }
          }
      });
    });
  }

  /**
   * Save new order to database
   * 
   * @param {Object} paymentData
   * 
   * @returns {Observable} Observable of orders
   */
  saveOrder(paymentData){
    return Observable.create( observer => {
      this.database.ref('orders').push(paymentData).then( data => {
        observer.next(data);
        observer.complete();
      });
    });
  }

  /**
   * Add payment requets. Server listens firebase backet with payments request and process coming requests
   * 
   * @param {Object} data PaymentData
   * @param {string} paymentMethod  name of payment method
   * 
   * @returns [firebase.database.ThenableReference]{@link https://firebase.google.com/docs/reference/js/firebase.database.ThenableReference}
   */
  addPaymentRequest(data, paymentMethod) {
    return this.database.ref('payment-request').push({
            data: data,
            payMethod: paymentMethod
        });
  }

  /**
   * Returns payment response by id
   * 
   * @param {string} paymentKey id of payment response. Payment request and payment response have same ids in their backets
   * 
   * @returns {Observable} Observable of payment response
   */
  listenPaymentResponse(paymentKey) {
    return Observable.create( observer => {
      this.database.ref('payment-response/' + paymentKey).on('value', data => {
        if(data.val()){
          observer.next(data);
        }
      });
    });
  } 


  /**
   * Send letter with password resetting to specific email 
   * 
   * @param {string} email User email
   * 
   * @returns      [firebase.Promise]{@link https://firebase.google.com/docs/reference/js/firebase.Promise} containing void
   */
  resetPassword(email) {
    return this.auth.sendPasswordResetEmail(email);
  }

  /**
   * Get order by Id
   * @param id id of order
   * @returns {Observable} Observable of order
   */
  getOrderById(id) {
    return Observable.create( observer => {
      this.database.ref('orders/' + id).on('value', data => {
        if(data.val()){
          observer.next(data.val());
        }
      });
    });
  }

  /**
   * Emits order object when new order added
   * 
   * @returns {Observable} Observable of new order
   */
  listenOrders() : Observable<any>{
    return Observable.create( observer => {
      this.database.ref('orders').on('child_added', newOrder => {
        if(newOrder.val()){
          observer.next(newOrder.val());
        }
      });
    })
  }

  getOrderSubject() {
    return this.orderSubject;
  }

  getSeoText(url: string, indexBlock: number) : Observable<any>{
    return Observable.create( observer => {
      this.database.ref('seo-text').orderByChild('url').equalTo(url).on('value', data => {
        if(data.val() && data.val() !== null){
          Object.keys(data.val()).map( key => {
            observer.next(data.val()[key]['blocks'][indexBlock]);
          });
        } else {
          observer.next(null);
        }
      });
    });
  }
}

results matching ""

    No results matching ""