BtoBtoC(BtoBtoBでも可)向けのアプリの場合、そのアプリを提供している会社向けに管理画面を提供したいと考えることがあります。その管理画面では、利用企業が自分たちのデータについてだけメンテナンスできるようになります。
そのための管理画面を作成していきます。今回は前回のベースを踏まえて、設定保存処理を作っていきます。
設定データは1社1行で
契約社数が増えるとその分データストアの行数が増えてしまいます。そこでなるべく行数が増えないデータ管理法を考える必要があります。項目数があまり多くないのであれば、1行にまとめて管理できるでしょう。
もし項目が多くなるのであれば、一つのフィールドにオブジェクトとして保存することもできます。
ACLを使ってデータを保存する
データはAclを使ってメンテナンスできるデータを制限します。そのため、各担当者はロールに所属することとします。ただし、担当者は自分が何のロールに所属しているかを知るすべがありません。そこで、会員データにカラムを追加して、そこにロール名を登録しておくことにします(今回はCompanyとしています)。
設定画面用のリンクを追加
ログインしたら設定画面に行くためのリンクを追加します。 views/index.jade に次のように追加します。
a.btn.btn-info(href='/configs') 設定
HTML(Jade)テンプレートの作成
テンプレートを作成します。views/config/index.jadeとして作成します。これはconfigで渡されたオブジェクトを表示しているだけです。
extends ../layout block content h1 設定画面 form(action='/configs',method='post') div.form-group label(for='inputAppName') アプリ名 input.form-control(type='text',name='appName',value=config.appName) div.form-group label(for='inputDescription') 概要 textarea.form-control(rows=10,cols=50,name='description')= config.description div.checkbox label input(type='checkbox',name='public',checked=(config.public ? 'checked' : undefined)) 公開 button.btn.btn-default(type='submit') 更新
routes/config.jsの作成
次に処理を行う routes/config.js を作成します。大枠として次のようになります。認証データや設定用クラスは各処理で使うので一番上で定義しておきます。
let express = require('express'); let router = express.Router(); let ncmb = require('../libs/ncmb'); // 認証データ let user = null; // 設定用のクラス let Config = ncmb.DataStore('Config'); // 認証処理など router.all('*', (req, res, next) => { }); // 表示処理 router.get('/', (req, res, next) => { }); // 保存、更新処理 router.post('/', (req, res, next) => { }); module.exports = router;
認証処理など
認証処理はすべての処理に関わるのでrouter.allで処理を行うのが良いでしょう。ここは全てのルーティングが通る処理になります。認証データはセッションに入っていますので、それがある場合とない場合で処理分けをします。
user = req.session.user || null; if (!user) { return res.redirect('/'); }else{ ncmb.sessionToken = user.sessionToken; next(); }
表示処理
表示処理ではConfigクラスのfetchを使ってデータを取得します。fetchは1件だけデータが返ってきます。それをそのまま画面表示に適用します。検索条件として、Company(企業名)を追加しておきます。これにより、自社のデータだけを抽出できます。設定データは認証していないユーザであっても読み取りはできる必要がありますので、このように絞り込みを行います。
Config.fetch() .where({Company: user.Company}) .then(config => { res.render('configs/index', { user: user, config: config }); }) .catch(error => { res.status(401).render('error', {error: error}); })
保存、更新処理
保存、更新処理ではまず表示処理と同様に現状のデータを取得します。データがない場合は新規作成を行いますので、ACLを設定します。今回はuser.Companyを使い、acl.setRoleReadAccessを使って自社向けに書き込み権限を付与しています。さらに管理者(アプリ開発企業)でもデータが操作できるようにAdminに対してもロールを追加しておきます。読み込みは認証していないアプリ利用者でもできる必要がありますのでsetPublicReadAccessを追加します。
appName/descriptionは文字列データなのでそのままsetメソッドを使って適用します。チェックボックスなどで真偽値を使いたい場合は別途変換が必要です。さらに検索時のフィルタリング用にCompanyを追加し、自社の企業名(ロール名)を登録しておきます。
そして最後にobjectIdの有無を確認してsave(新規作成)またはupdate(更新)メソッドを実行します。
Config.fetch() .where({Company: user.Company}) .then(config => { if (Object.keys(config).length === 0) { // 新規作成 config = new Config; // Acl設定 let acl = new ncmb.Acl; acl.setRoleWriteAccess(user.Company, true) .setRoleWriteAccess('Admin', true) .setPublicReadAccess(true); config.set('acl', acl); config.set('Company', user.Company); } let ary = ['appName', 'description']; for (let i in ary) { let name = ary[i]; config.set(name, req.body[name]); } config.set('public', req.body.public === 'on'); if (config.objectId) { return config.update(); }else{ return config.save(); } }) .catch(error => { res.status(401).render('error', {error: error}); }) .then(config => { res.render('configs/index', { user: user, config: config }); })
ルーティングに追加
最後にconfigs.jsをルーティングに追加します。これは app.js に追記します。
var configs = require('./routes/configs'); app.use('/configs', configs);
ここまでの処理で、各企業ユーザー向けに1行分の設定画面ができあがりました。100企業ユーザあったとしても100行で済みますので特に問題にならないでしょう。さらにAdminロールを追加しておくことで、アプリ開発企業もデータをSDKから操作できます。
今回までのコードはNCMBMania/BtoB_Management at v0.2にて確認できます。実装時の参考にしてください。