Ubuntu 19.04のRedmineでチケットのインポートができない件


Ubuntu 19.04のRedmineでチケットのインポートを使用としたらInternal Errorが発生してしまったので、その対策を備忘録として。

エラーログ

Redmineでチケットのインポートを実行しようとするとInternal Errorが発生してしまった。
ログを見るとテンポラリ・ディレクトリ /usr/share/redmine/tmp が作れないと怒っている。

/var/log/redmine/default/production.log
Started POST "/redmine/imports" for 10.0.2.2 at 2019-08-01 21:27:22 +0900
Processing by ImportsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Tu6seP+IyMKIaygRfO/+M8PQJMNpGivSgatqyITRM4+UE4zgtKatyGJPJQXQRy4KF/QjwWmeSnKNsjIyBDQRHw==", "file"=>#<ActionDispatch::Http::UploadedFile:0x0000561984bab5c8 @tempfile=#<Tempfile:/tmp/RackMultipart20190801-5413-mxkmnf.csv>, @original_filename="test.csv", @content_type="application/vnd.ms-excel", @headers="Content-Disposition: form-data; name=\"file\"; filename=\"test.csv\"\r\nContent-Type: application/vnd.ms-excel\r\n">}
  Current user: katsuya (id=5)
Completed 500 Internal Server Error in 15ms (ActiveRecord: 7.8ms)

Errno::EACCES (Permission denied @ dir_s_mkdir - /usr/share/redmine/tmp):

lib/redmine/utils.rb:49:in `save_upload'
app/models/import.rb:47:in `file='
app/controllers/imports_controller.rb:35:in `create'
lib/redmine/sudo_mode.rb:63:in `sudo_mode'

調べてみると /usr/share/redmine 以下に tmp というディレクトリは存在しなかった。

安易すぎる修正

まずは、すごくすごく安易に修正してみる。

$ cd /usr/share/redmine
$ sudo mkdir tmp
$ sudo chmod a+wrx tmp

これでも、とりあえず動く。
tmp の下に更に imports というディレクトリができていて、オーナーは www-data になっていた。

安直にディレクトリを作ってパーミッションを設定すればそれなりに動くようになるのだけど、この手のディレクトリ/ファイルは /var 以下にすべきと考える。
/usr/share/redmine/tmp ではなく /var/chache/redmine/<instance>/tmp

気持ちが悪いので/usr/share/redmine/tmp はスカッと削除。

$ sudo rm -fr /usr/share/redmine/tmp

抜本的対策

Redmineの実行ファイルを探してみると、以下のファイル (一部抜粋) が怪しい。

/usr/share/redmine/app/models/import.rb
  # Returns the full path of the file to import
  # It is stored in tmp/imports with a random hex as filename
  def filepath
    if filename.present? && filename =~ /\A[0-9a-f]+\z/
      File.join(Rails.root, "tmp", "imports", filename)
    else
      nil
    end
  end

Rubyは解らないのだが、Rails.root ではなく、インスタンスのルートにすべき。
ということで、他のファイルと見比べてみて Rails.rootRedmine.root に書き換える。
ついでに、日付フォーマットもよく使うYYYY/MM/DD形式が使えるようにする。

--- /usr/share/redmine/app/models/import.rb.org 2019-01-20 15:57:15.000000000 +0900
+++ /usr/share/redmine/app/models/import.rb 2019-08-02 10:36:11.694010187 +0900
@@ -28,6 +28,7 @@
   validates_length_of :filename, :maximum => 255

   DATE_FORMATS = [
+    '%Y/%m/%d',
     '%Y-%m-%d',
     '%d/%m/%Y',
     '%m/%d/%Y',
@@ -78,7 +79,7 @@
   # It is stored in tmp/imports with a random hex as filename
   def filepath
     if filename.present? && filename =~ /\A[0-9a-f]+\z/
-      File.join(Rails.root, "tmp", "imports", filename)
+      File.join(Redmine.root, "tmp", "imports", filename)
     else
       nil
     end

これでOK。目的の場所に imports ディレクトリが作成された。

なお、パッチは自己責任で使用ください。