arc の日記

はてなダイアリーから引っ越してきました。さらに新しい記事は https://junkato.jp/ja/blog/ で書いています。

DokuWikiのユーザ管理をMySQLに差し替え

オープンソースプロジェクトMaterealでは、ドキュメント管理・情報共有にWikiを使っています。Wikiエンジンは様々なものがありますが、日本語、英語など多言語で自由に記事を作れて、それなりにユーザ管理などの仕組みもあり、積極的に開発が続けられている…という条件で選ぶと意外と少なく、現在のところDokuWikiに落ち着いています。

DokuWikiは初期状態で全てのデータをプレーンテキストで保持するようになっており、登録ユーザ一覧についても同様です。 dokuwiki/conf/users.auth.php に以下のような生データが置いてあります。

# users.auth.php
# <?php exit()?>
# Don't modify the lines above
#
# Userfile
#
# Format:
#
# user:MD5password:Real Name:email:groups,comma,seperated

admin:$1$hogefuga:arc@dmz:arc@example.com:admin,user

とある事情で認証に使われるデータベースをMySQLに差し替えたので、記録を残しておきます。なお、公式サイトのWiki内に必要最低限の情報が載っているんですが、ちょっと分かりづらいです。「移行」でなく「差し替え」と書いているのは、元のユーザとグループの数が少なく実データについては手動で移行したためです。

MySQLデータベースを準備する

認証情報を格納するためのテーブルを作ります。

-- ユーザ情報を格納する dw_users
CREATE TABLE IF NOT EXISTS `dw_users` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `login` varchar(20) NOT NULL DEFAULT '',
  `pass` varchar(60) NOT NULL DEFAULT '',
  `name` varchar(255) NOT NULL DEFAULT '',
  `email` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`uid`),
  UNIQUE KEY `login` (`login`)
);

-- グループ情報を格納するdw_groups
CREATE TABLE IF NOT EXISTS `dw_groups` (
  `gid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `gname` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`gid`),
  UNIQUE KEY `name` (`gname`)
);
-- userグループ、adminグループを作成
INSERT INTO `dw_groups` (`gid`, `gname`) VALUES (1, 'user'), (2, 'admin');

-- ユーザとグループの包含関係を格納するdw_usergroup
CREATE TABLE IF NOT EXISTS `dw_usergroup` (
  `uid` int(10) unsigned NOT NULL DEFAULT '0',
  `gid` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`uid`,`gid`)
);

ユーザ情報を移行したいなら次のようにすればOKです。

-- ユーザ登録
INSERT INTO `dw_users` (`uid`, `login`, `pass`, `name`, `email`) VALUES
(1, 'admin', '$1$hogefuga', 'arc@dmz', 'arc@example.com');

-- 登録したユーザをuser,adminグループに入れる
INSERT INTO `dw_usergroup` (`uid`, `gid`) VALUES (1, 1), (1, 2);

MySQL用の設定ファイルを作る

まず dokuwiki/conf/mysql.conf.php を作ります。 dokuwiki/conf/mysql.conf.php.example というのがありますが、これを書き換えるのは面倒でしょうから以下書き換えたあとの内容を転載します。

<?php
$conf['auth']['mysql']['server']   = 'mysql.example.com';
$conf['auth']['mysql']['user']     = 'mysqlusr';
$conf['auth']['mysql']['password'] = 'mysqlpwd';
$conf['auth']['mysql']['database'] = 'mysqldb';

/* MySQLのデバッグメッセージ出力。OFF。 */
$conf['auth']['mysql']['debug'] = 0;
/* パスワードはPHP側で暗号化してからMySQLに送るので平文パスは送らない。 */
$conf['auth']['mysql']['forwardClearPass'] = 0;
/* 操作時にロックするテーブル一覧 */
$conf['auth']['mysql']['TablesToLock']= array("dw_users", "dw_users AS u","dw_groups", "dw_groups AS g", "dw_usergroup", "dw_usergroup AS ug");

/* 以下ユーザ認証などで使うSQL文 */
$conf['auth']['mysql']['checkPass']   = "SELECT pass
                                         FROM dw_usergroup AS ug
                                         JOIN dw_users AS u ON u.uid=ug.uid
                                         JOIN dw_groups AS g ON g.gid=ug.gid
                                         WHERE login='%{user}'
                                         AND gname='%{dgroup}'";
$conf['auth']['mysql']['getUserInfo'] = "SELECT pass, name, email AS mail
                                         FROM dw_users
                                         WHERE login='%{user}'";
$conf['auth']['mysql']['getGroups']   = "SELECT gname as `group`
                                         FROM dw_groups g, dw_users u, dw_usergroup ug
                                         WHERE u.uid = ug.uid
                                         AND g.gid = ug.gid
                                         AND u.login='%{user}'";
$conf['auth']['mysql']['getUsers']    = "SELECT DISTINCT login AS user
                                         FROM dw_users AS u
                                         LEFT JOIN dw_usergroup AS ug ON u.uid=ug.uid
                                         LEFT JOIN dw_groups AS g ON ug.gid=g.gid";
$conf['auth']['mysql']['FilterLogin'] = "login LIKE '%{user}'";
$conf['auth']['mysql']['FilterName']  = "name LIKE '%{name}'";
$conf['auth']['mysql']['FilterEmail'] = "email LIKE '%{email}'";
$conf['auth']['mysql']['FilterGroup'] = "gname LIKE '%{group}'";
$conf['auth']['mysql']['SortOrder']   = "ORDER BY login";
$conf['auth']['mysql']['addUser']     = "INSERT INTO dw_users
                                         (login, pass, email, name)
                                         VALUES ('%{user}', '%{pass}', '%{email}',
                                         '%{name}')";
$conf['auth']['mysql']['addGroup']    = "INSERT INTO dw_groups (gname)
                                         VALUES ('%{group}')";
$conf['auth']['mysql']['addUserGroup']= "INSERT INTO dw_usergroup (uid, gid)
                                         VALUES ('%{uid}', '%{gid}')";
$conf['auth']['mysql']['delGroup']    = "DELETE FROM dw_groups
                                         WHERE gid='%{gid}'";
$conf['auth']['mysql']['getUserID']   = "SELECT uid AS id
                                         FROM dw_users
                                         WHERE login='%{user}'";
$conf['auth']['mysql']['delUser']     = "DELETE FROM dw_users
                                         WHERE uid='%{uid}'";
$conf['auth']['mysql']['delUserRefs'] = "DELETE FROM dw_usergroup
                                         WHERE uid='%{uid}'";
$conf['auth']['mysql']['updateUser']  = "UPDATE dw_users SET";
$conf['auth']['mysql']['UpdateLogin'] = "login='%{user}'";
$conf['auth']['mysql']['UpdatePass']  = "pass='%{pass}'";
$conf['auth']['mysql']['UpdateEmail'] = "email='%{email}'";
$conf['auth']['mysql']['UpdateName']  = "name='%{name}'";
$conf['auth']['mysql']['UpdateTarget']= "WHERE uid=%{uid}";
$conf['auth']['mysql']['delUserGroup']= "DELETE FROM dw_usergroup
                                         WHERE uid='%{uid}'
                                         AND gid='%{gid}'";
$conf['auth']['mysql']['getGroupID']  = "SELECT gid AS id
                                         FROM dw_groups
                                         WHERE gname='%{group}'";

最後に、このスクリプトDokuWikiから読まれるように、 dokuwiki/conf/local.protected.php に次の行を足します。このファイルがない場合は作成してください。

<?php
    require_once('mysql.conf.php');
?>

認証方法をMySQLに変える

Webから、 dokuwiki/?do=admin&page=config の認証のセクションで、認証方法(ACL)をplainからmysqlに変え、デフォルトグループ(ACL)をuserからadminに変えます。

前段で管理者のユーザ情報を移行してあれば何事もなくログインできますが、そうでなければ新たに管理者にしたいユーザ名で新規登録して、そのユーザでログインします。デフォルトグループがadminになっているので管理者ユーザとしてログインできるはずです。

管理者としてログインしたらデフォルトグループ(ACL)をadminからuserに戻します。

以上です。