Sphereとともに

scalaとかplayframeworkとか。技術ブログにしたいなと。環境は Windows7x64, mac です。たまに声優さん情報が混ざります。最近ちょっとClojure触りました。

Angular + firebase with playframework(scala)

Angular

app.component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule, AngularFireAuth } from 'angularfire2/auth';
import { AuthService } from './auth.service'

import * as firebase from 'firebase/app';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    user: Observable<firebase.User>;
    constructor(public afAuth: AngularFireAuth, public authService: AuthService) {
      this.user = afAuth.authState;
    }
    login() {
      this.afAuth.auth.signInWithPopup(new firebase.auth.TwitterAuthProvider());
    }
    logout() {
      this.afAuth.auth.signOut();
    }
    auth() {
      firebase.auth().currentUser.getToken().then(token => this.authService.auth(token).subscribe(
        s => console.log(s),
        e => console.log(e)
      ))
    }
}

auth.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions, Jsonp } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import * as firebase from 'firebase/app';


@Injectable()
export class AuthService {
  private authUrl = '/api/auth';

  constructor(private http: Http, private jsonp: Jsonp) { }

  auth(token: any): Observable<any> {
    let headers = new Headers({ 'Content-Type': 'application/json' });
    // "Access-Control-Allow-Origin", "*"
    let options = new RequestOptions({ headers: headers });

    let data = {token: token};

    return this.http.post(this.authUrl, JSON.stringify(data), options)
                    .map(this.extractData)
                    .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body.data || { };
  }

  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

playframework

package modules

import java.io.FileInputStream
import javax.inject.Singleton

import com.google.firebase.{FirebaseApp, FirebaseOptions}
import com.google.inject.AbstractModule

import collection.JavaConverters._

/**
  * Created by fscoward on 2017/05/28.
  */
class FirebaseModule extends AbstractModule {
  def configure() = {
    bind(classOf[Firebase])
      .asEagerSingleton
  }
}

@Singleton
class Firebase {
  lazy val options = new FirebaseOptions.Builder()
    .setServiceAccount(new FileInputStream("秘密のjsonファイル名"))
    .setDatabaseUrl("https://<プロジェクト名>.firebaseio.com/")
    .build()

  FirebaseApp.getApps.asScala.toList match {
    case Nil => FirebaseApp.initializeApp(options)
    case list => println(list.mkString)
  }
}

AuthController

package controllers

import javax.inject.Inject
import javax.inject.Singleton

import com.google.firebase.auth.{FirebaseAuth, FirebaseToken}
import com.google.firebase.tasks._
import play.api.mvc.{Action, Controller}

/**
  * Created by fscoward on 2017/05/25.
  */
@Singleton
class AuthController @Inject()() extends Controller {
  def auth = Action(parse.json) { implicit req =>
    val firebaseAuth = FirebaseAuth.getInstance()
    val task: Task[FirebaseToken] = firebaseAuth.verifyIdToken((req.body \ "token").as[String])
    val result = Tasks.await(task)
    Ok(result.getUid)
  }
}

Scalaスケーラブルプログラミング第3版

Scalaスケーラブルプログラミング第3版