こんにちは,五十嵐です.今回は deleteuser,edituser と searchuser です.Catalyst を使用したデータベースの処理については,今回で 4 回目ですが,これで,データベースを操作する一通りの処理ができるようになります.

delete ユーザでの注意点は一点."admin" を削除しないようにすることです."admin" を管理用の固定ユーザとして使用します.
まず,削除できるかどうかを確認するための is_deletableuser() を作成します.データベースを検索するので,$c と $user_id を引数として渡します.
lib/SecureSBM/Controller/Admin.pm
sub is_deletableuser : Private {
my( $c, $user_id ) = @_;
if( $user_id eq '1' ){ # for admin
return '';
}
ユーザ ID が 1 かどうかを判断しています.admin の id は 1 ですので,この部分でチェックします.
if( my $udb = $c->model('SecureSBMDB::User')
->find({user_id => $user_id}) ){
my $udbname = $udb->user_email;
if( $udbname eq '' || $udbname eq 'admin' ){
return '';
}else{
return $udb;
}
}
"user_email" フィールドが admin かどうかを再度確認します.registuser の処理ではあまり説明しませんでしたが,同じ名前は登録できないようにチェックしています.基本的に admin というユーザはひとつしか存在しないはずですが,念のために確認しています.$c->log->debug() はログメッセージを出力するもので,'-Debug' オプションが指定されていなければ,出力されません.
データベースの検索でエラーが出れば,空文字を返します.
この is_deletableuser() を使用して,削除を判断します.
lib/SecureSBM/Controller/Admin.pm
sub deleteuser : Local {
my ( $self, $c, $user_id ) = @_;
my ($udb, $urdb);
$c->stash->{resultmessage}
= 'ユーザー[' . $user_id . ']は削除できませんでした.';
if( $user_id ){
if( is_deletableuser( $c, $user_id ) ){
if( $urdb = $c->model('SecureSBMDB::UserRole')
->search({user_id => $user_id}) ){
if( $udb = $c->model('SecureSBMDB::User')
->search({user_id => $user_id}) ){
$urdb->delete_all;
$udb->delete_all;
$c->stash->{resultmessage}
= 'ユーザー[' . $user_id . ']を削除しました.';
}
}
}
}
$c->forward('listusers');
}
以上で,deleteuser が完成です.これで登録と削除のテストが行えます.
次に,edituser を作成します.同様に Admin.pm に追加します.
lib/SecureSBM/Controller/Admin.pm
sub edituser : Local {
...(略)
# 引数の受け渡し
foreach my $k ( qw/user_id user_email user_surname user_name
user_password user_password2/ ){
$data{$k} = $c->req->param( $k );
}
渡された引数を %data に格納します.
# email の小文字化
$data{user_email} =~ tr/A-Z/a-z/;
email のアドレスは常に小文字.
# 固定ユーザの確認
if( !($udb = is_deletableuser( $c, $data{user_id} )) ){
$data{user_email} = $udb->user_email;
}
変更してよいユーザかどうかを確認して,変更してはいけないユーザの場合には,データベースにあるメールアドレスを再設定します.
if( my $useremail = $data{user_email} ){
# 既登録かどうかを確認
if( my $tbl = $c->model('SecureSBMDB::User')
->find({user_email => $useremail}) ){
if( $data{user_id} != $tbl->user_id ){
$c->stash->{resultmessage} = "ユーザ(E-mail)["
. $useremail
. "]は既に登録されています.";
$c->forward('listusers');
return 1;
}
}
}
ログイン名として使用するので,メールアドレスの重複を確認します.
# パスワードの変更確認
# 確認用パスワードだけ入力されていた場合には無視
if( $data{user_password} ){
if( $data{password} ne $data{password2} ){
$c->stash->{resultmessage}
= "確認用パスワードが一致しません.";
$c->forward('listusers');
return 1;
}
$setpassword = 1;
}
パスワードの変更を確認します.
foreach my $k ( qw/user_id user_email user_surname user_name/ ){
$udb->set_column( $k, $data{$k} );
}
変更するカラムを設定します.
if( $setpassword ){
$udb->set_column('user_password',
Digest::SHA::sha1_hex( $data{'user_password'} ) );
$c->log->debug("*** setpassword: $setpassword");
}
パスワードのダイジェスト作成.
データベースのアップデート.
$c->stash->{resultmessage}
= "ユーザ ID: $data{user_id} を変更しました.";
$c->forward('listusers');
}
最後に listusers へ処理を渡します.
これで,リスト(lisusers),登録(registuser),変更(edituser),削除(deleteuser) ができあがりました.

これはユーザ編集の画面です.
残すは,検索(searchuser)です.ちょっと長くなりますが,やっつけてしまいましょう(とりあえず,完全一致のみ検索).
lib/SecureSBM/Controller/Admin.pm
sub searchuser : Local {
...(略)
if( my $useremail = $data{user_email} ){
$useremail =~ tr/A-Z/a-z/;
if( my $udb = $c->model('SecureSBMDB::User')
->find({user_email => $useremail}) ){
(見つかった旨のメッセージを $resultmessage へ)
}else{
(見つからなかった旨のメッセージを $resultmessage へ)
}
}
$c->stash->{resultmessage} = $resultmessage;
$c->forward('listusers');
}
もう,説明することもないですね.form からパラメータを受け取って,find で検索するだけです.
現在の状態では,入力されたものがそのまま出力されますので,クロスサイトスクリプティングに利用されてしまいます.ためしに名前などに "<script>alert("Ooops!");</script>" と入力して登録してみてください.listusers を呼び出したときに alert ウィンドウが表れるはずです.このような状態は,出力チェックを行っていないために発生します.このようなセキュアプログラミングに関しては,後ほど改めて変更したいと思います.
ユーザに関する処理が一通り終わりましたので,同様にして,Role, Tag, Bookmark について作成します.詳細は省きますが,手順はほぼ同じです.
2007/03/23 記
参考:
Keyword: Perl Catalyst Secure-SBM SSBM セキュア・ソーシャル・ブックマーク