タイトル/名前 | 更新者 | 更新日 |
---|---|---|
画像/Java/java_charactercode_2_1.jpg | msakamoto-sf | 2008-12-23 13:43:29 |
画像/Java/java_charactercode_1_sjis.jpg | msakamoto-sf | 2008-12-23 13:35:18 |
画像/Java/java_charactercode_1_plus.jpg | msakamoto-sf | 2008-12-23 13:34:43 |
画像/Java/java_charactercode_1_plus2.jpg | msakamoto-sf | 2008-12-23 13:34:09 |
画像/Java/java_charactercode_1_euc.jpg | msakamoto-sf | 2008-12-23 13:33:21 |
日記/2007/10/31/YakiBikiのACLメモ | msakamoto-sf | 2008-12-23 13:20:42 |
日記/2007/10/16/YakiBikiの基本方針メモ | msakamoto-sf | 2008-12-23 12:59:26 |
日記/2007/06/28/YakiBikiのライセンスメモ | msakamoto-sf | 2008-12-23 12:40:25 |
日記/2007/10/12/Xhwlayメモ | msakamoto-sf | 2008-12-23 00:56:52 |
日記/2007/09/11/Xhwlayメモ | msakamoto-sf | 2008-12-23 00:54:29 |
当初は U2A 、つまり「ユーザーID(と、アクセスレベル)を元に対応するACL IDを取得する」インデックスを作成する予定だった。これについては諸々の思考の後も変わらない。但しインデックスではなく、「ACLキャッシュ」という独立した概念となり、daoやidxとしては実装されない。恐らく、yb直下、つまりYakiBiki内の機能を横断する位置づけとなるだろう。まぁ実際、YakiBikiのデータ操作の殆どに関わってくるので、この扱いでも良いだろう。
ACLキャッシュは、次のような機能を提供する。
現在既に、ACL IDに対応するDataIDを取得する"A2D"インデックスが存在する。これとACLキャッシュを組み合わせることで、次の手順で、アクセスが許可されるデータIDを取得可能になる。
例えばトップ画面になるであろう一覧表示であれば、この結果とカテゴリやキーワード検索のインデックス取得結果を併せ、更新ソートインデックスにフィルタとして適用することで、現在ログイン中のユーザーがアクセス可能なデータの検索結果を取得できる。
また、編集画面や単一表示画面などある一つのIDに対して追跡したい場合は、逆にデータを先に取得しそのACL-IDが、1.の結果に含まれているかで対象となる操作のallow/denyを判別可能となる。
ACLキャッシュはあくまでもキャッシュである為、ユーザー・グループ・ACLに変更が生じた場合適宜再構築する必要がある。
具体的にどのタイミングで再構築が必要となるのか。その前にまず、ユーザー・グループ・ACLに変更が生ずるタイミングを確認する。
以上が変更タイミングとなる。注意点として、ACLのupdateには例えばPolicy(Negative/Positive)だけの修正や、権限リストだけの修正も含まれる。
さて、ここで実際にACLキャッシュが「無効」となり、再構築が必要となるタイミングを絞り込んでみる。結論から言うと以下に絞り込まれる。
以下に、これら以外がなぜ除外されたのか理由を述べる。
ちなみに、delete { user | group } の処理には当然 add / remove も含まれている。しかし、処理のI/Fとしてメソッド(ロジック)を分割してしまっている為、別タイミングとして挙げている。
またACLのcreateタイミングに於いては、create時点で既に権限リストが初期データとして渡される可能性がある為、再構築の要有りと判断している。
各ACLキャッシュ再構築タイミングでの詳細を述べる前に、ACLデータを以下にして「キャッシュ」にconvertするのかその概要を、現状の段階でメモしておく。
まず、ACLデータの構成を改めて確認する。
アクセスレベル とはアクセス権限を表す整数値・・・今のところは、である。現時点では以下の3つのうちいずれかの値を取る。
policyは二つの値を持つ。 Positive と Negative である。POSI/NEGAとも省略する。以下に、policyがどのように権限リストの評価に影響するのかをまとめてみる。
次のような権限リストを想定してみる。
権限リストの評価に於いては、一旦グループを、その所属するユーザーに展開する。従って上記リストは次のように変形される。
このように、一つのUserIDに対して、グループを展開したことにより複数のアクセスレベルが同居する事になる。この優先順位を決定するのがpolicyとなる。
なお、権限リスト中のアイテムの上下関係は優先順位とは影響しない。つまり、上下関係は処理上なんら意味を持たない。
Positive policy とは一言で言えば、要求されたアクセスレベル 以上が一つでもあれば許可 するポリシーである。
Negative policy とは一言で言えば、要求されたアクセスレベル 未満が一つでもあれば拒否 するポリシーである。
ACLデータと実際の許可・拒否の判定基準は上記のような評価によって定められる。今のところは。
ACLキャッシュの原理は、ACLデータに登録されているユーザーの分だけ、上記評価結果を何らかの物理ファイルとしてキャッシュしておく仕組みである。
基本的には他のインデックス系と似たようなデータファイル構造を取る。
cache/ acl/ 1.idx (UserID = 1) 2.idx (UserID = 2) 3.idx (UserID = 3) ...
#ACLID,LEVEL|OK_NG&LEVEL|OK_NG&LEVEL|OK_NG&... 100,1|1&2|0 200,1|0&2|0 300,1|1&2|1 ...
なおLEVELについては、"0"は登録されない。LEVEL 0 は評価時に使われる。外部から「Level0についてこのユーザーが許可されているACLを取得したい」というケースはあり得ない。なぜなら、Level0はアクセス禁止を表しているからである。
概要 | 入力 | 出力 |
---|---|---|
許可されるACL ID群の取得 | ユーザーID, アクセスレベル | 一つ以上のACL ID |
ユーザーと関わるACL ID群の無条件取得 | ユーザーID | 一つ以上のACL ID |
ユーザーIDのエントリの作成, 削除 | ユーザーID | 処理の成否 |
キャッシュの新規作成・更新 | ユーザーID, ACL ID | 処理の成否 |
キャッシュの削除 | ユーザーID, ACL ID | 処理の成否 |
(以上は現時点での暫定予想。)
ACLキャッシュの原理と、権限リストとpolicyの評価の仕組みを踏まえた上で、各再構築タイミングにおける処理の詳細を考えてみる。
その前に、処理の簡略化のため、新たに G2A という1:Nインデックスを追加する。これは、 アクセスレベルに関わらず 権限リストに登録されているグループと、ACL IDを結びつけるためのものである。詳細は後述。
まずユーザーを削除できるための条件を確認しておく。そのユーザーがownerとなっているGroup, Category, Data, Acl が全て0件となっていることが必須条件である。実際はこの条件を満たすための確認作業が面倒くさいため、結局、ステータスを「ログイン禁止」にして無効化する措置が採られるとは思うのだけれど・・・。さておき。
グループの削除条件は特に無い。なぜならグループIDが他と関係するのは、UserIDとのリレーションと、このACL権限リストだけだからである。
これについては先に例を挙げた方が分かりやすい。ユーザーがグループより脱ける場合、グループに入る場合のそれぞれを考えてみる。
以下のような権限リストを持つACLを考えてみる。
ここで、user1がgroup1から脱けるとする。その場合、 キャッシュとして 影響するのは、user1のエントリのみである。user2が、user1と同じくgroup1に所属しているが、 user2の評価結果はなんら変化しない。 このため、キャッシュを更新するのはuser1のエントリに絞ることが可能となる。
以下のような権限リストを持つACLを考えてみる。
ここで、user2がgroup1に入るとする。その場合、 キャッシュとして 影響するのは、user2のエントリのみである。user1やuser3が、同じくgroup1に所属しているが、 user1, user3の評価結果はなんら変化しない。 このため、キャッシュを更新するのはuser2のエントリに絞ることが可能となる。
addもremoveも、次のような処理で共通になることが分かった。
まだまだ悩みまくっていた時のメモ。
ここから大分変わってしまっていて、ACL絡みのインデックスも今では acl_to_data の1つしかない。
U2AやG2Aは結局不要となってしまって消えた。
ACLの再構築タイミングは殆どそのまま。
ACLの評価については、現時点では yb_AclCache クラスの normalize_permlist() と evaluate() メソッドに集約されている。仕様についてはテストケースを参照。まぁ評価の内実については上記メモからあまり変わっていない。グループからユーザを展開して、衝突についてはPolicyで解決するという流れ。
alpha-2の段階ではACLがグループの操作やカテゴリ操作、記事スレッドの操作にも及んでいたのだけれど、面倒くさくなったので alpha-3の時にマスタ管理は個別のroleに持たせて、記事スレッドの概念も削除。記事の作成権限を別途roleに含ませる事でその辺を管理するように直したりしている。
随分久しぶりに・・・。この間、Xhwlayをやっていたから。4ヶ月ぶり。
とりあえず、基本方針だけメモ。
言葉が悪いようであれば、「実装しないでおく」。或いは「考えないでおく」。ようするに「後回し」。
非常に難しいのだけれど、とにかく、鳥羽口を開く為の0.0.1を作る為には、これを徹底するほか無い。
これだけは捨てられない。
インデントはスペース4つ分。 →趣味。
80桁改行。 →趣味。
テスト駆動開発。 →クラスを作るときの、外部I/Fの「スケッチ」としての効果がある。厳密なエラー系まではまだ考慮せず、「こんな感じでこのクラスは動くだろう~。」を描く効果があるので、採用する。
0.0.1が動けば、あとはどうにかなる。状況を、動かす事ができる筈。
2008年12月時点での感想
なんだかんだ言っておきながら、結構捨てられないモノもありました。
とにかく2007年の10月 - 12月はかなりアレコレ悩んだ事は確かです。大凡の仕様は頭にありましたが、詳細を詰めていったりACLとの連携を考えたり、実際にクラスや作りに落とし込む時の方針など、いくら悩んでも悩み足りないという感じでした。
こういう時、やはり相談できる人がいたら、もう少しスピードも上がっていたと思います。なまじ一人で考え込んでしまうと、「ほどほどでこの辺で落とし込んでおけばいいだろう」というブレーキが働かず、結構疲れました。
PukiWikiはGPLなんだけど・・・再改造したソースを「頒布しない自由」も保障したいので、PukiWikiのコードは使えない。
KinoWikiは奇跡的に修正BSDライセンスだから、こっちをベースにするしかねーよ!!
まあ・・・もともと、PukiWikiじゃなくてKinoWikiをベースにするつもりだったから良いのだけれど。ちょうどOOP + Smartyだから非常に助かる・・・。
PEARを頒布物に含められるか同かが実は生命線だったのだけれど、
http://pear.php.net/group/docs/20040402-la.php
によると、ApacheStyle, PHPLicense, LGPL, BSDStyle, MITStyleで再頒布可能なので、・・・BSDLicenseだな・・・。
いや、修正BSDライセンスのコードを取り込んだものをApacheStyleでリリースできるか?はちょい問題。ああ・・・でも、大丈夫か・・・。何か言われたらBSDに戻せばよいか・・・。
Log4phpが、まずいんだよな。LGPLからApache Software License Ver 2.0 に変更されてる。
う~~ん・・・とりあえず、修正BSD(newBSD)にしておいて、まずかったらApacheLicense 2.0に戻すか・・・。
2008年12月現在、結局XhwlayがAPL2.0なので、YakiBikiもAPL2.0にしています。
はてダの方でも簡単に書いていますが、XhwlayのPHPによる実装であるxhwlay-phpの最初のbetaバージョンをリリースします。
簡単にまとめたWebコンテンツも同時にリリースしますので、ご興味のある方はご覧下さい。
http://xhwlay.sourceforge.net/
Xhwlay-0.9.0はPEAR形式でインストールできます。インストール後、PEARのdocsディレクトリに sample が入ります。これに関する簡単なPDFのチュートリアルドキュメントも書いてみました。PDFのDLは、上のURLの日本語ページから入手できますので、こちらも宜しければどうぞ。
・・・長かったよぅ。
後述の通り失敗に終わるのですが、折角なのでチャネルサーバの作り方について書いてあるURLをメモ。
とりあえずチャネルサーバを立ててみるか、と、SF.netのWebサーバ環境に、go-pear.phpを入れようとする。
[msakamoto-sf@pr-shellE htdocs]$ wget http://go-pear.org/ --01:20:57-- http://go-pear.org/ => `index.html' Resolving go-pear.org... 216.92.131.66 Connecting to go-pear.org|216.92.131.66|:80... failed: Connection refused.
・・・ん?Connection refused?
試しにローカルに一旦落としたgo-pear.phpをUPって、コマンドラインから
$ php go-pear.php
しても、同様のエラーでアウト。
コマンドラインからじゃNGかと思い(*1)、Apacheからやってみるも、今度は chmod 777 した筈のPEARインストールディレクトリが悉く、パーミッションエラーで弾かれてる。
どうなっているのか、とApacheのプロセスを見ようとすると、
root ... /usr/sbin/vmware-guestd --background /var/run/vmware-gues
VMwareのゲスト用デーモン!?へぇ・・・VMware上で動いていたのか・・・。全然気づかなかった。
で、結局Apacheプロセスが見えなかった。うーん・・・ドキュメントを見てみるか(*2)。
https://sourceforge.net/docs/E07
E07- 09 Outbound Connectivity
・・・ご免なさいご免なさいご免なさい。ちゃんと明記してありましたね。Webサーバ環境からは、他のSourceForgeサーバも含めて一切内→外へのアクセスはシャットダウンしてあるのでした。
ちょっと待て。
これじゃ、PEARインストールできないじゃん?
確かにまぁ、ローカルで疑似環境作ってUPれば良いと言えば良いのだけれど、そこまでするのは正直、面倒くさい。ひどく。
と言うことで、Xhwlayのチャネルサーバを立てるのは諦めます。
やっぱり、自前の鯖を使わないと無理そう。とはいえ、殆ど変更が入らないコントローラ系のライブラリで、そこまでするか?というのはある。
まあ海外の安い、rootをもらえるホスティングサービスと契約するのはアリだし、いつかはそれをやろうとは思っているけど、9-11月にかけて身辺が非常にごとごとする可能性が高く、アッチこっちに手を回す余裕がないのも確か。
というわけで、Xhwlayのチャネルサーバは断念します。
2008年12月時点ではOpenPEARがありますので、試してみたいですね・・・。
チャネルサーバが無いと、パッケージの魅力は半減するように思えるので正直諦めようとか思っていたのだけれど、せっかくなので作ってみようか。と、思う。
WEB+DBの33号も参考にしてみる。PEAR_PackageFileManager をインストールすると、doc_dir に当たるディレクトリに幾つかのExampleスクリプトがインストールされるので、それを参考に弄ってみる。
で。
相当の紆余曲折の末、SummaryやDescriptionはサンプルそのままだが、とりあえずパッケージを作ることができた。また、その作業により
generatePackage.xml.php
を新たにリポジトリに追加した。(SVNの作業ディレクトリを丸ごとごっそり移動したばっかりだったので、上手くcommitできるか不安だったが特に問題なかった。よかったにゃ~。)
中身の細かい値は今後修正していくが、とりあえずコレがスケルトンになる。
$ rm package.xml package2.xml # なぜか削除しておかないと上手く動かない? $ php generatePackage.xml.php ... ... (XMLが生成され、標準出力に出力される。validateも行われ、何かエラーがあれば表示される) ... (エラーが無く、XMLも特に問題ないようであれば実際にpackage.xml/package2.xmlを作成・保存) $ php generatePackage.xml.php make ^^^^ これが追加される。 $ $ ls ... Xhwlay-X.X.X.tgz ... $ pear info Xhwlay-X.X.X.tgz ... (パッケージの情報を確認) $ pear list-file Xhwlay-X.X.X.tgz ... (ファイルのインストール先を確認)
こんな感じで。
・・・色々紆余曲折がありました。最初は、WEB+DB 33号の記事やExampleのスクリプトのつぎはぎから始まったので、XMLのvalidateで何回も怒られた。っつーか、validateする前にも表示してくれるとどこがどう悪いのか分かりやすいんだが。
で、ようやくvalidateが無くなったと思ったら、「XMLで指定されたファイルが、現実には無いよ?」という感じのERRORが。
Error: File "C:/in_vitro/SVNWORK/xhwlay-php\hwlay/Bookmark.php" in package.xml does not exist Error: File "C:/in_vitro/SVNWORK/xhwlay-php\ample/templates/pages_default.html" in package.xml does not exist
・・・ん?
xhwlay-php\hwlay => xhwlay-php\Xhwlay ^ xhwlay-php\ample => xhwlay-php\sample/ ^
の間違いじゃない?
で、いろいろsetOptionの値を確認したり、ソースコードを追っかけてる内に、 ひょっとしたらBUGかもしれない箇所を発見 。すごい分かりづらいのだけれど、
PEAR/PackageFileManager/File.php#getFileList() ... $path = substr(dirname($file), strlen(str_replace( DIRECTORY_SEPARATOR, '/', realpath($package_directory))) + 1); ^^^ ここが怪しい。
やっている内容は、例えば 'packagedirectory' が
C:/your/package/directory
であった時、次のファイルが来たら、
C:/your/package/directory/foo/bar.php
'packagedirectory'分をさっぴいて返す。つまり
C:/your/package/directory/foo/bar.php - C:/your/package/directory = foo/bar.php
にする、という処理。
で、どうやら、'packagedirectory' の末尾が"/"で終わっている場合、+1が効いてしまい、"/"の直後1文字まで削られる。つまり、
C:/your/package/directory/foo/bar.php - C:/your/package/directory/f = oo/bar.php
となってしまうらしい。
良く動いてるよな・・・。 というかこれ、本当にBugなのか?実は単なる自分の設定ミスでちゃんと設定するモノしていれば問題なかったりして。
とにかく、本当かウソか分からないので、一応patch作ってPEARのBugとしてreportしておいた。
http://pear.php.net/bugs/bug.php?id=12023
さて、どうなるか・・・。
これで、PEARのBugレポート、二回目だな。外れクジ引いてるような気が。
あと、PEARの入力フォームが全般的に使いづらい。今回も、例によりAccount忘れたので新規作成したのだけれど、UserNameやFullNameで、やれ大文字小文字、ALNUMしか駄目だとか、 POSTした後に怒られるし。 しかも、 入力画面にはそんな注意書きないし。
なので、エラーになる度、CAPTCHA入力し直し。おまけに 必須入力の強調表示が無い為、すごい分かりづらい し。
UserNameやパスワード、FullNameなどでは、入力可能な文字数が表示されていないし。
うーん、ユーザーインターフェイスというのを考えたことがあるのか?これもBugというよりはRequestとしてレポートを作れと?うへぇ。