[node.js] sailsで非公開のModelを作成する

sailsのmodel機能はグローバルに呼び出せるmodelクラスを簡単に作ることができます。  
しかもプロパティを定義するとそのmodelを呼び出せるCRUDなAPIまでも作ってくれます。  

しかし時には「APIの公開はしたくないけど内部的にはアクセスしたい」ということがあります。その設定方法です。

## 環境
node v0.10.33  
npm 2.1.18  
sails 0.10.5  

(DBはmongodbを使用)

## おおまかな手順

1. sails new hoge(サイトの新規作成)
2. sails generete api fuga (モデルとコントローラーを作成)
3. 外部からのapiアクセスを遮断する

## 手順
### 1: 新規作成

sails newして新規作成したらgitの設定もやってしまいますので、bitbucketに同名の新規リポジトリを作っておきます。  
私はmasterブランチでは一切作業をしないので、devブランチを作ってチェックアウトしておきます。

```
cd /path/to/directory
sails new hogeProject
git init
git remote add origin git@bitbucket.org:myname/hogeProject.git
git add -A
git commit -m 'init'
git push origin master
git checkout -b dev
```

### 2: モデルとコントローラーの作成

```
sails generate api sites --coffee
```
coffeeオプションを付けるとcoffee-scriptでモデルとコントローラーが新規作成されます。  

新規に作成されたapi/models/Sites.coffeeを編集します。  
name,url,dataのプロパティを設定します。

```Sites.coffee
module.exports =
  attributes:
    name:
      type: 'string'
      required: true
    url:
      string:
        url: true
        maxLength: 100
      required: true
    data: 'json'
```
(上記でurl:trueとかしているけどバリデーションできてません。知ってる方教えてください)

次にsailsとmongodbのコネクションを設定します。
別でmongodbが動いていることが前提ですが、詳細は割愛します。

`config/connections.js`を開いて`someMongodbServer`の部分を自分の環境に書き換えます。
user,passwordは設定しなくても動きますが、外部から直接dbのURLを叩いたらアクセスできてしまうのでぜひ設定しましょう。  
詳細はこちらで。  
[node.jsからリモートサーバーのmongoDBに接続する方法 - Qiita](http://qiita.com/_wats/items/a6d5501c8cf1cf82c1c0)

```config/connections.js
  someMongodbServer: {
    adapter: 'sails-mongo',
    host: 'localhost',
    port: 27017,
    user: 'username',
    password: 'password',
    database: 'test_app_db'
  },
```

databaseの部分でdb名を設定できます。  
設定しない場合のdb名は[sails]になります。
同一のサーバーで複数のsailsを起動した時のために設定しておきましょう。



次に`config/env/development.js`を開いてコメントアウトされてる部分を有効化します。

```config/env/development.js
  models: {
    connection: 'someMongodbServer'
  }
```

---

sailsでmongodbを使うときにはsails-mongoが必要ですのでコマンドラインからインストールしておきます。

```
npm install sails-mongo@0.10.x -S
```

mongoを起動してconfig/connections.jsで設定したdatabaseを作成します。

```
# mongo
MongoDB shell version: 2.6.5
connecting to: test
> use test_app_db
switched to db test_app_db
> db.test.insert({id:'123'})
WriteResult({ "nInserted" : 1 })
> db.addUser('username','password')
WARNING: The 'addUser' shell helper is DEPRECATED. Please use 'createUser' instead
Successfully added user: { "user" : "username", "roles" : [ "dbOwner" ] }
```

`use test_app_db`の部分でdbが作成できますが、exitすると消えてしまうのでダミーのデータをinsertします。  
続いてこのdbにユーザーを追加します。先ほどのusernameとpasswordを設定します。  
'addUser' じゃなくて'createUser'使えよ、と警告が出ましたが追加は成功したようです。

---

sails liftして起動するとmigrateを決めろと言われるので1のsafeを選択します。  
デプロイして本番環境で動かす時はこの設定になるので、最初からそうしておきます。

それでは試しにAPI経由でsitesにデータを入れてみます。

```
# curl http://localhost:1337/sites -d "name=fxx&url=http://fxx.api.black"
{
  "name": "fxx",
  "url": "http://fxx.api.black",
  "createdAt": "2015-02-25T06:50:13.852Z",
  "updatedAt": "2015-02-25T06:50:13.852Z",
  "id": "54ed70a5deb80238ad4c9747"
}
```

成功したら新規で追加されたデータが表示されます。


### 3: 外部からのapiアクセスを遮断する
このままの状態では、誰でも上記のURLからDBを操作できてしまいます。安全の為にAPI経由でのCRUDを禁止しましょう。
config/policies.jsに以下の設定を追記します。

```config/policies.js
  SitesController: {
    '*': false
  }
```

sailsを再起動して再度追加してみます。

```
# curl http://localhost:1337/sites -d "name=hoge&url=hogehogefoo"

Forbidden
```

外部からの操作はできなくなりました。

しかし内部的には`Sites`がグローバルに定義されていますので、`Sites.find()`等のメソッドで操作できます。

以上です。