SphinxをShinatraでホストしつつGithubのOAuth経由でチーム認証をかけたが


Sphinxで作成したドキュメントをherokuでホスティング、Continuous Documentationなススメ(Basic認証付き) の外伝。
『Basic認証』 => 『Github認証+特定のチームに属するかで閲覧可』 に変更してみたコード。

困った

認証箇所で困った

  • Basic認証はRackモジュールだったのでpublix含む全リクエストが対象だった
  • Github連携のsinatra_auth_githubはSinatraの仕様に依存、=> publicへのアクセスにフィルタがかけられない

= 1.0 / 2010-03-23
-- snip --
* Filters do not run when serving static files anymore. (Ryan Tomayko)
https://github.com/sinatra/sinatra/blob/master/CHANGES

publicに依存しまくっているSphinxホスティングはsinatra1.0でのこの変更が非常に厳しい。

モンキーパッチで解決してしまった

Important: The following notes on Sinatra::Base and Sinatra::Application are provided for background only - extension authors should not need to modify these classes directly.
http://www.sinatrarb.com/extensions.html

すまない公式、Sinatra::Baseオープンです。beforeフィルタをpublic(static)配信時にも実行するように猿りました。

問題のコード

config.ru
require 'sinatra'
require 'sinatra_auth_github'
set :public_folder, File.dirname(__FILE__) + '/build/html'

use Rack::Session::Cookie,
  :secret => Digest::SHA1.hexdigest(rand.to_s),
  :expire_after => 3600

set :github_options, {
  :scopes    => "user",
  :secret    => ENV['GITHUB_CLIENT_SECRET'],
  :client_id => ENV['GITHUB_CLIENT_ID'],
}

@@github_team = ENV['GITHUB_TEAM_ID']

register Sinatra::Auth::Github


## Monkey for static filter
module Sinatra
  class Base
    class_eval do
      alias :org_static! :static!
      def static!
        filter! :before
        org_static!
      end
    end
  end
end

## user is team_member?
before do
  if request.path_info.end_with?('.html')
    begin
      body = github_team_authenticate!(@@github_team)
    rescue
      ## return securocat!
      halt 401, body
    end
  end
  if request.path_info == '/logout'
    logout!
    redirect 'https://github.com'
  end
end

get '/' do
  redirect "/index.html", 301
end

not_found do
  unless request.path_info.end_with?('.ico')
    redirect "#{request.path_info}.html", 301
  end
  halt 404
end

run Sinatra::Application

認証

とりあえず*.htmlへのリクエストに対して、Github未ログインorアプリ認証許可なしならGithubへ飛ばします。Github認証が済んでおり、特定のチームに所属するならドキュメントを閲覧OK。

そうでない奴はsecurocatさんにご登場願う仕様になりました。

モンキーパッチ脱出案?

  • RackのミドルウェアとしてSinatraの前で認証をかける
  • publicを使わずあくまでgetで処理し、File.exists?file_sendで頑張る

どうしたものかと。