LoopBack (Open SourceのBaaS)を使ってみよう! その1. PostgreSQL接続とTwitter認証
あるiOSアプリを作ろうとしています、このアプリはバックエンドのサーバーと情報をやり取りします。バックエンドのサーバーはRuby on Railsで作ってもよいのですが、なるべく早くプロトタイプを動かしたいので、今回は既存のBaaS(Backend as a Service)を使ってみる事にしました。
!
1. なぜ LoopBack を使う事にしたのか
現在BaaSのサービス、Open Sourceのソフトはたくさんあります。ネット上でいろいろと調べてみると BaaS にもサービスよりのものとプラットフォームよりのものがあります(この分類は、私がそう思っているだけかもしれません)。
サービスより のもとしては、実際に良く使われている Parse があげられます。Parseはプッシュ通知やアプリのデータ同期・共有などを複数のプラットフォーム(iOS,Android,PC...)に提供するサービスです。
プラットフォームより のものとしては、Loopbackや以前は話題になったdeploydなどがあります。これらはスマフォとやり取りするAPIサーバーを構築するためのフレームワークやクラウドです。 LoopbackはOpen Sourceのソフトですが、それをクラウドで提供するStrongLoopのような会社もあります。
BaaSは現在も進化・競争している世界で、どのサービス・ソフトが良いのかは 簡単には決められない世界のようです。詳しくはBaaSはまだ戦国時代だったのか、まとめ。(執筆中)が参考になります。
今回、Loopbackを使う事にした理由は
- プラットフォームよりで、今回作るアプリに適切
- Open Sourceなので、突然のサービス停止にも泣かない
- ドキュメントもそれなりにある
- いろいろとサンプルコードがある
- Node.jsベース。Node.jsはまだまだ初心者ですが Ruby/Railsの世界感にも近い
- サーバーを自前で準備する必要があるが、このへんは慣れいてる
2. LoopBack入門
a. 前提条件
LoopBackを使うには、Node.js を使って簡単なWebアプリを作れる知識・経験が必要だと思います。
- JavaScript
- Node.js
- npm コマンド
- 英語ドキュメントが読める (LoopBackの日本語の情報はほぼありません)
b. 入門
- node.jsのインストール (v0.10.xを使って下さい。v0.11.xでは動きません)
- LoopBackのGetting startedページを試す
- Ruby on Railsの scaffold のようなものです
- Modelを定義すると、そのモデルのCRUD操作が出来るREST APIサーバーが出来ます
- プロジェクトの構成、設定ファイルの役割等を知って下さい
- ドキュメントを読みましょう(先にExamplesを試しても良いですが、たぶん読まないと詰まります)
- LoopBackのExamplesの興味があるものを試す
- Examplesのリンク先はGitHubです
- 詳しい手順が書かれています。たいてい git clone して設定ファイル等を変更し実行する流れです
- 手順通りにやっても動かない事もままあります。がんばって対応しましょう、とても勉強になります ^^;
- コードはJavaScriptで書かれています、問題になっているコードを読んでみましょう
3. LoopBackをPostgreSQLにつなぐ
概要
LoopBackはいろいろなDBと接続出来るようになっていますが、大きく2つのタイプがあります
- MongoDBのようなダイナミックDB
- RDB
- このタイプのDBを使う場合はModelにはプロパティー(カラム)の定義が必要です
- MySQL, PostgreSQL, Oracle, SQL Serverなど主要なRDB用のコネクターが準備されています
- 先ずはGitHubのloopback-example-databaseをcloneして動かしてみるのが良いと思います
- ドキュメントはData sources and connectorsとPostgreSQLをつかうならPostgreSQL connector
設定ファイル
LoopBackではDBと接続するための設定ファイルがいくつかあります
- server/datasources.json : 接続するDBの定義ファイル。
- 複数のDBを使う事が出来ます
- Memory DBは最初から定義されています
- PostgreSQLの定義ファイルにはDatabase名、login、passwordやサーバーなどの情報を書きます、他のソフトでもよくあるものだと思います。
{ "db": { "name": "db", "connector": "memory" }, "pgDB": { "name": "pgDB", "connector": "postgresql", "port": 5432, "debug": true, "database": "node_test", "username": "node_test", "password": "node_test" } }
- server/model-config.json: Modelの一覧と、Modelが使うDBなどの定義。
- 最初の _meta の sources は Modelファイルのある場所のリスト
{ "_meta": { "sources": [ "../common/models", "./models", "./node_modules/loopback-component-passport/lib/models" ] }, "user": { "dataSource": "pgDB", "public": true }, .... "Role": { "dataSource": "db", "public": false } }
- common/models/Model名.json : Modelの定義
- 対応するRDBのテーブル名、カラム名、型や関連などを定義します
- optionsを指定する事で、細かいテーブル・カラムの設定が書けます
- 定義の意味はData sources and connectorsと下位のページに書かれていますが、全てが網羅された情報は無いようです(?)
- デフォルトでは、Model名、プロパティー名がテーブル名、カラム名にそのまま使われます。対応を変えたい場合はoptionsで指定する必要があります
- テーブルにはプライマリーキーが必要です、idInjectionをtrueにすればRailsのように整数型のidカラムが自動生成されます
- 関連情報relationsにはRails同様に hasMany, belongsTo が定義出来ます
{ "plural": "users", "base": "User", "options": { "postgresql": { "table": "users" } }, "idInjection": true, "properties": { "username": { "type": "String", "required": true }, "password": { "type": "String", "required": true } }, "relations": { "accessTokens": { "type": "hasMany", "model": "accessToken", "foreignKey": "userId" } }, "validations": [], "acls": [], "methods": [] }
- 他の例
- 特定のカラムをプライマリーキーにしたい場合は、idInjectionをfalseにし、プロパティーにid属性を指定をします。
{ "name": "accessToken", "plural": "accessTokens", "base": "AccessToken", "options": { "postgresql": { "table": "access_tokens" } }, "idInjection": false, "properties": { "id": { "type": "String", "id": 1, "required": false }, "ttl": { "type": "Number", "required": false }, "userId": { "type": "Number", "postgresql": { "columnName": "user_id" }, "required": false }, "created": { "type": "Date", "required": false } }, "validations": [], "relations": {}, "acls": [], "methods": [] }
- server/create-test-data.js : テーブルの作成とテストデータの作成
- このファイルは自動生成されないので、Exampleからコピーして作る必要があります。
var server = require('./server'); var dataSource = server.dataSources.accountDB; var Account = server.models.account; var accounts = [ { email: 'foo@bar.com', created: new Date(), modified: new Date() }, { email: 'bar@bar.com', created: new Date(), modified: new Date() } ]; var count = accounts.length; dataSource.automigrate('account', function(er) { if (er) throw er; accounts.forEach(function(account) { Account.create(account, function(er, result) { if (er) return; console.log('Record created:', result); count--; if(count === 0) { console.log('done'); dataSource.disconnect(); } }); }); });
4. LoopBackでTwitter/Facebookの認証を使う
概要
LoopBackにはThird-party loginとい機能があり、これを使うと簡単にTwitter/Facebookの認証を使う事ができます。
- この機能はloopback-component-passport コンポーネントをインストールする事で実現できます
- GitHubのloopback-example-passportをcloneして動かしてみるのが良いと思います
- ドキュメントはThird-party login
- Twitterの consumerKey, consumerSecret は予め入手しておいて下さい
設定ファイル
設定ファイルは providers.json で loopback-example-passportには providers.json.template が用意されているのでコピーして使ってください。
- Twitterは http://localhost で確認できますが、Facebookは動作しないようです
{ "local": { "provider": "local", "module": "passport-local", "usernameField": "username", ... "twitter-login": { "provider": "twitter", "authScheme": "oauth", "module": "passport-twitter", "callbackURL": "http://localhost:3000/auth/twitter/callback", "authPath": "/auth/twitter", "callbackPath": "/auth/twitter/callback", "successRedirect": "/auth/account", "consumerKey": "ここにconsumerKeyを指定", "consumerSecret": "ここにconsumerSecretを指定" }, .... }
5. LoopBackでPostgreSQL接続とTwitter認証
PostgreSQLに接続し、Twitter認証が行えるようにしてみました。 GitHubに loopback-example-passportをPostgreSQL対応した例 を置きました、これを参考にして下さい。
- PostgreSQLのテーブル定義は、後々の事を考えRuby on Railsのルールに合わせました
- providers.jsonはTwitterの consumerKey, consumerSecretを入手し作って下さい
- server/create-test-data.js を実行するとテーブルが作成されます
- loopback-example-passportは Memoryを使っているので、user モデルにカラム定義がありませんが server/datasources.json に file属性を指定するとDBをファイルにJSONで保存してくれるのでそれを見てカラム定義は作りました
- user モデル以外の認証に必要なモデルの定義はThird-party+loginに書かれています
ドキュメントには書かれてない部分があったり、callbackの中で起こるエラーはtracebackが在っても役に立たず苦労しました ^^);