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が在っても役に立たず苦労しました ^^);