読者です 読者をやめる 読者になる 読者になる

redmine タイムゾーン、autologin

Ruby

今まで、社内のWindowsサーバーで動かしていた 社内情報Redmineも新しく契約したサーバーに移行しました。
しかし、また問題が・・・


タイムゾーン

海外にあるサーバーなので、当然タイムゾーンが日本と違います。細かい事ですが、チケットの作成、変更時間が日本時間ではありません。

しかし、Rails 2.1 でタイムゾーンがサポートされたので簡単に解決しました。

config/environment.rb に以下を追加するだけ

  config.time_zone = 'Tokyo'

ログインしないでチケットの一覧を取得したい

以前 http://d.hatena.ne.jp/yuum3/20070904/1188888674 に書いたように、私は複数Trac/Redmineの情報を CGI で集めて使っています。今回移動した 社内情報Redmine は非公開なのでログインしないとチケット情報が見えません。Tracの場合はベーシック認証なので簡単なプログラムで対応できますが、Redmine は独自のログインを持っているので対応が難しそう・・・ と思っていたのですが、ソースを読んでいると autologinという機能がありました。


これは、Redmineの設定(認証)で自動ログインを有効にすると、autologin という名前の Cookie で自動的ログインできるようになります。Cookie を送るには簡単なので、簡単にこの問題も対応できました ^^)/

ただし、セキュリティー的には弱くなるので注意して運用して下さいね。


Redmine autologin に対応した mulit_trac.rb

#!/usr/local/bin/ruby
#
#  複数のTrac/Redmineのチケットを表示するCGI
#
require 'yaml'
require 'uri'
require 'net/http'

def load_config(conf_path)
  YAML.load_file conf_path
end

def get_ticket_list(conf)
  Net::HTTP.version_1_2
  host, port, path = URI.split(conf['url']).values_at(2,3,5)
  http = Net::HTTP.new(host, port ? port : 80)
  http.open_timeout = 5
  http.read_timeout = 5
  http.start {|http|
    $stderr.puts "GET #{host} #{port.to_s} #{path} (#{conf['login']})" 
    req = Net::HTTP::Get.new(path)
    req.basic_auth(conf['login'], conf['password'])   if (conf['login'])
    req['Cookie'] = "autologin=" + conf['autologin']  if (conf['autologin'])
    response = http.request(req)
    $stderr.puts " len = #{response.body.length}"
    return response.body
  }
rescue TimeoutError
  return ""
end

def get_table_body(html)
  html =~ /<tbody>(.*)<\/tbody>/m
  $1.to_s.gsub(/(\n *)+/, "\n")
end

def add_title(title, new_ticket_url, head_span, bot_span, body)
  %Q!<tr><td colspan="#{head_span}">#{title}</td><td colspan="#{bot_span}"><a href="#{new_ticket_url}" target="_blank">チケット登録</a> </td></tr>\n! + body
end

def adjust_href_url(url, html)
  url =~ /(https?:\/\/.*?)\//
  http_server = $1
  html.gsub(/href=\"\/(.*)\"/, "href=\"#{http_server}/\\1\" target=_blank")
end

def put_http_header
  puts "Content-type: text/html; charset=UTF-8"
  puts ""
end

def put_page_header
  puts <<HEADER
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title> 未解決チケット一覧 </title>
  <link rel="stylesheet" href="/css/trac.css" type="text/css" />
  <link rel="stylesheet" href="/css/report.css" type="text/css" />
  <link rel="stylesheet" href="/css/redmine.css" type="text/css" />
</head>
<body>
HEADER
end

def put_page_footer
  puts <<FOOTER
</body>
</html>
FOOTER
end


def put_trac_table_header
  puts <<TRAC_HEADER
  <table class="listing tickets">
    <thead>
    <tr>
      <th>Ticket</th> <th>Summary</th> <th>Component</th> <th>Version</th> <th>Milestone</th> <th>Type</th> <th>Owner</th> <th>Created</th>
    </tr>
    </thead>
    <tbody>
TRAC_HEADER
end

def put_trac_table_footer
  puts <<TRAC_FOOTER
    </tbody>
  </table>
TRAC_FOOTER
end

def put_redmine_table_header
  puts <<REDMINE_HEADER
<table class="list issues">
  <thead><tr>
    <th></th><th>No.</th><th>トラッカー</th><th>ステータス</th><th>優先度</th><th>題名</th><th>担当者</th><th>更新日</th>
  </tr></thead>
  <tbody>
REDMINE_HEADER
end


def put_redmine_table_footer
  puts <<REDMINE_FOOTER
    </tbody>
  </table>
REDMINE_FOOTER
end



configs = load_config 'tracs.yaml'
trac_table_bodys = configs.select{|conf| conf['soft'] == 'trac'}.map {|conf|
  add_title(conf['title'], conf['url'].sub(/report\/1$/, 'newticket'), 2, 6,
            get_table_body(adjust_href_url(conf['url'], get_ticket_list(conf)))) }
redmine_table_bodys = configs.select{|conf| conf['soft'] == 'redmine'}.map {|conf|
  add_title(conf['title'], conf['url'] + "/new", 4, 3,
            get_table_body(adjust_href_url(conf['url'], get_ticket_list(conf)))) }

put_http_header
put_page_header

put_trac_table_header
trac_table_bodys.each {|t| puts t}
put_trac_table_footer

put_redmine_table_header
redmine_table_bodys.each {|t| puts t}
put_redmine_table_footer

put_page_footer