module Omnigollum::Sinatra

Public Class Methods

registered(app) click to toggle source
# File lib/omnigollum.rb, line 188
def self.registered(app)
  # As options determine which routes are created, they must be set before registering omniauth
  config  = Omnigollum::Config.new

  options = app.settings.respond_to?(:omnigollum) ?
    config.default_options.merge(app.settings.send(:omnigollum)) :
    config.default_options

  # Set omniauth path prefix based on options
  OmniAuth.config.path_prefix = options[:route_prefix] + OmniAuth.config.path_prefix

  # Setup test_mode options
  if options[:dummy_auth]
    OmniAuth.config.test_mode = true
    OmniAuth.config.mock_auth[:default] = {
      'uid' => '12345',
      "info" => {
        "email"  => "user@example.com",
        "name"   => "example user"
        },
        'provider' => 'local'
      }
    end
  # Register helpers
  app.helpers Helpers

  # Enable sinatra session support
  app.set :sessions,  true

  # Setup omniauth providers
  if !options[:providers].nil?
    app.use OmniAuth::Builder, &options[:providers]

    # You told omniauth, now tell us!
    config.eval_omniauth_config &options[:providers] if options[:provider_names].count == 0
  end

  # Populates instance variables used to display currently logged in user
  app.before '/*' do
    @omnigollum_enabled = true
    @user_authed = user_authed?
    @user        = get_user
  end

  # Stop browsers from screwing up our referrer information
  # FIXME: This is hacky...
  app.before '/favicon.ico' do
    halt 403 unless user_authed?
  end

  # Explicit login (user followed login link) clears previous redirect info
  app.before options[:route_prefix] + '/login' do
    kick_back if user_authed?
    @auth_params = "?origin=#{CGI.escape(request.referrer)}" unless request.referrer.nil?
    user_auth
  end

  app.before options[:route_prefix] + '/logout' do
    user_deauth
    kick_back
  end

  app.before options[:route_prefix] + '/auth/failure' do
    user_deauth
    @title    = 'Authentication failed'
    @subtext = "Provider did not validate your credentials (#{params[:message]}) - please retry or choose another login service"
    @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
    show_error
  end

  app.before options[:route_prefix] + '/auth/:name/callback' do
    begin
      if !request.env['omniauth.auth'].nil?
        user = Omnigollum::Models::OmniauthUser.new(request.env['omniauth.auth'], options)

        case (authorized_users = options[:authorized_users])
        when Regexp
          user_authorized = (user.email =~ authorized_users)
        when Array
          user_authorized = authorized_users.include?(user.email) || authorized_users.include?(user.nickname)
        else
          user_authorized = true
        end

        # Check authorized users
        if !user_authorized
          @title   = 'Authorization failed'
          @subtext = 'User was not found in the authorized users list'
          @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
          show_error
        end

        session[:omniauth_user] = user

        # Update gollum's author hash, so commits are recorded correctly
        session['gollum.author'] = {
          :name => options[:author_format].call(user),
          :email => options[:author_email].call(user)
        }

        redirect request.env['omniauth.origin']
      elsif !user_authed?
        @title   = 'Authentication failed'
        @subtext = 'Omniauth experienced an error processing your request'
        @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
        show_error
      end
    rescue StandardError => fail_reason
      @title   = 'Authentication failed'
      @subtext = fail_reason
      @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
      show_error
    end
  end

  app.before options[:route_prefix] + '/images/:image.png' do
    content_type :png
    send_file options[:path_images] + '/' + params[:image] + '.png'
  end

  # Stop sinatra processing and hand off to omniauth
  app.before options[:route_prefix] + '/auth/:provider' do
    halt 404
  end

  # Pre-empt protected routes
  options[:protected_routes].each {|route| app.before(route) {user_auth unless user_authed?}}

  # Write the actual config back to the app instance
  app.set(:omnigollum, options)
end