RailsでMCImageManger, MCFileManagerを使う
Posted by yatsu Sun, 29 Oct 2006 01:21:30 GMT
JavaScriptで作られたHTMLエディタはいくつかありますが、僕はTinyMCEが好きで、よく使っています。 Railsアプリに組み込むのも簡単で、少しJavaScriptコードをいじるだけで、AjaxでロードしたテキストエリアにTinyMCEを組み込むこともできます。
TinyMCEがさらにすごいのは、MCImageManagerとMCFileManagerというプラグインをもっていることです。 MCImageManagerは画像をアップロードすることができ、GDを使ってサムネイルも作ってくれます。 MCFileManagerは想像どおりの機能をもっています。 また、MCImageManagerとMCFileManagerは相互に連携することが可能です。
これらは単にTinyMCEのプラグインというだけでなく、単独でアプリに組み込むこともできるのが素晴らしいです。 どちらも売り物なので買わなければなりませんが、値段は高くないので、充分買う価値はあると思います。
MCImageManagerとMCFileManagerはこのように素晴らしいものですが、PHPで作られているというのがひとつの難点です。 ファイルをアップロードするときはたいていユーザー認証が必要となりますが、組み込み元のアプリがRailsの場合、それを実現するには、PHPからRailsのセッションとユーザー権限を参照しなければなりません。 そのやり方については、TinyMCE Forumに質問されているのを見つけましたが、具体的なやり方は見つかりませんでした。 ということで、ここに僕のやり方を書いておきます。
MCImageManager/MCFileManagerは認証の枠組をもっており、プラグインという形でそれを拡張できるようになっています。 そのため、コードをどこに記述し、どのように拡張するかは問題ではありません。 PHPとRailsでのセッション/権限情報の受け渡しだけが問題となります。
セッション/権限情報の受け渡し方法としては以下の2つの方法が考えられます。
- RailsのセッションをDBに保存し、PHPがそのセッション情報と権限を取得し認証する
- PHPからRailsにHTTPリクエストを送ってRails側に認証させる
まず1を検討します。 セッション情報をDBに保存するには、config/environment.rb で
config.action_controller.session_store = :active_record_store
とするだけでよいので非常に簡単ですが、セッションに保存されたデータは sessions テーブルの data フィールドに Marshal.dump の結果が格納されます。
セッションが有効かどうかチェックするだけであれば問題ありませんが、セッションからユーザー情報を取得し権限をチェックする必要がある場合、data フィールドの中身を Marshal.load しなければなりません。
PHP自身でそれをやるのは困難ですし、Rubyのスクリプトを作って呼び出そうとすると、Railsのライブラリ群をロードしなければならず(それがないとクラス情報が足りなくてエラーになります)、起動に時間がかかってしまいます。
sessions テーブルにカラムを追加してユーザー情報を取りやすくすることもできないわけではありませんが、ActiveRecordをこのために拡張するのはきれいでないし、実装も面倒です。
1は難しそうなので、2の方法を検討します。
RailsのセッションIDはCookieの _session_id で渡されており、MCImageManager/MCFileManagerを開いたときもこのCookieが渡されるので、PHPからRailsのセッションIDを取得することは可能です。
このセッションIDをCookieにセットして、PHPからRailsへ、ローカルホストのWebサーバーを介してリクエストを送って認証結果を返してもらえばよさそうです。
PHPにはCURLライブラリがあるので、HTTPリクエストを送るのは簡単です。
ということで、2の方法で実装することとします。
まず、Rails側に認証用のコントローラを作成します。
app/controllers/php_controller.rb
class PhpController < ApplicationController
before_filter :set_content_type
def authonticate
if <認証が通ったら> # お好きなように実装してください
render :text => "OK"
else
render :text => "NG"
end
end
protected
def set_content_type
@headers["Content-Type"] = "text/plain; charset=UTF-8"
end
end
単純にテキストで “OK” または “NG” を返すようにしています。
User Engineを使用している場合は以下のようにすればよいでしょう。
def authenticate
controller = params["controller"]
action = params["action"]
if user? and current_user.authorized?(controller, action)
render :text => "OK"
else
render :text => "NG"
end
end
次に、MCImageManagerのプラグイン・ディレクトリにRailsAuthenticatorというものを作成します。
imagemanager/classes/Plugins/RailsAuthenticator.php
<?php
class RailsAuthenticator extends BaseAuthenticator {
var $_sessionId;
function init(&$config) {
$this->_sessionId = $_COOKIE["_session_id"];
}
function getGroups() {
return "";
}
function isLoggedin() {
if (!isset($this->_sessionId))
return false;
// Railsの認証用URLに書き換えてください
$ch = curl_init("http://127.0.0.1:8101/php/authenticate");
// レスポンスを返り値で受け取る
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// CookieにRailsのセッションIDをセット
curl_setopt($ch, CURLOPT_COOKIE, "_session_id=$this->_sessionId");
// リクエストを送信し、結果を受信
$ret = curl_exec($ch);
curl_close($ch);
if ($ret != "OK")
return false;
return true;
}
}
?>
これを読み込むように、imagemanager/config.phpの上の方に、以下を加えます。
require_once("classes/Plugins/RailsAuthenticator.php");
つづいて、認証クラスとしてRailsAuthenticatorが使用されるように、設定を書き換えます。
//$mcImageManagerConfig['authenticator'] = "BasicAuthenticator";
$mcImageManagerConfig['authenticator'] = "RailsAuthenticator";
認証に失敗したときにMCImageManagerのログイン画面が表示されてしまうと都合が悪いので、以下も変更しておきます。
//$mcImageManagerConfig['general.login_page'] = "login.php";
$mcImageManagerConfig['general.login_page'] = "not_loggedin.php";
以上、意外と簡単に認証を統合することができました。 上の例はMCImageManagerの場合ですが、MCFileManagerもほとんど同じ方法で実装できます。
ちなみに、上で作成したRailsの認証用URLをチェックするには、コマンドラインからcurlを使うのが便利です(-b でCookieを設定できます)。
% curl -b _session_id=772a295669eb5bcfa9435d723ba1e941 \
http://127.0.0.1:8101/php/authenticate
