Class: Orange::Middleware::AccessControl

Inherits:
Base show all
Defined in:
lib/orange-more/administration/middleware/access_control.rb

Overview

This middleware locks down entire contexts and puts them behind an openid login system. Currently only supports a single user id.

Instance Method Summary collapse

Methods inherited from Base

#call, #initialize, #inspect, #orange, #pass, #recapture

Constructor Details

This class inherits a constructor from Orange::Middleware::Base

Instance Method Details

#access_allowed?(packet) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/orange-more/administration/middleware/access_control.rb', line 56

def access_allowed?(packet)
  return true unless @locked.include?(packet['route.context'])
  if packet['user.id'] || packet['orange.globals']['main_user'] == false
    if @single && (packet['user.id'] == packet['orange.globals']['main_user'] )
      true
    elsif @single
      # Current id no good. 
      packet['user.id'] = false
      packet.session['user.id'] = false
      false
    # Main_user can always log in (root access)
    elsif packet['user.id'] == packet['orange.globals']['main_user']
      orange[:users].new(packet, :open_id => packet['user.id'], :name => 'Main User') unless packet['user', false]
      true
    else
      orange[:users].access_allowed?(packet, packet['user.id'])
    end
  else
    false
  end
end

#handle_openid(packet) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/orange-more/administration/middleware/access_control.rb', line 82

def handle_openid(packet)
  if packet.request.path.gsub(/\/$/, '') == @logout
    packet.session['user.id'] = nil
    packet['user.id'] = nil
    after = packet.flash('user.after_login') || '/'
    packet.reroute(after)
    return false
  end
  packet.reroute('/') if packet['user.id'] # Reroute to index if we're logged in.
  
  # If login set
  if packet.request.post?
    packet['template.disable'] = true
    # Check for openid response
    if resp = packet.env["rack.openid.response"]
      if resp.status == :success
        packet['user.id'] = resp.identity_url
        
        packet['user.openid.url'] = resp.identity_url
        packet['user.openid.response'] = resp
        # Load in any registration data gathered
        profile_data = {}
        # merge the SReg data and the AX data into a single hash of profile data
        [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response|
          if data_response.from_success_response( resp )
            profile_data.merge! data_response.from_success_response( resp ).data
          end
        end
        
        if packet['user.id'] =~ /^https?:\/\/(www.)?google.com\/accounts/
          packet['user.id'] = profile_data["http://axschema.org/contact/email"]
          packet['user.id'] = packet['user.id'].first if packet['user.id'].kind_of?(Array)
        end
        
        if packet['user.id'] =~ /^https?:\/\/(www.)?yahoo.com/
          packet['user.id'] = profile_data["http://axschema.org/contact/email"]
          packet['user.id'] = packet['user.id'].first if packet['user.id'].kind_of?(Array)
        end
        
        
        after = packet.flash('user.after_login') || '/'
        
        # Save id into session if we have one.
        packet.session['user.id'] = packet['user.id']
        
        # If the user was supposed to be going somewhere, redirect there
        packet.reroute(after)
        false
      else
        packet.flash['error'] = resp.status
        packet.reroute(@login)
        false
      end
    # Set WWW-Authenticate header if awaiting openid.response
    else
      packet[:status] = 401
      packet[:headers] = {}
      id = packet.request.params["openid_identifier"]
      id = "http://#{id}" unless id =~ /^https?:\/\//
      packet.add_header('WWW-Authenticate', Rack::OpenID.build_header(
            :identifier => id,
            :required => [:email, "http://axschema.org/contact/email"]
            ) 
      )
      packet[:content] = 'Got openID?'          
      return packet.finish
    end
  # Show login form, if necessary
  else
    packet[:content] = orange[:parser].haml('openid_login.haml', packet)
    return packet.finish
  end
end

#init(opts = {}) ⇒ Object

Sets up the options for the middleware

Parameters:

  • opts (Hash) (defaults to: {})

    hash of options

Options Hash (opts):

  • :openid (Boolean)

    Whether to use openid logins or not (currently only option)

  • :handle_login (Boolean)

    Whether the access control system should handle presenting the login form, or let other parts of the app do that.

  • :config_id (Boolean)

    Whether to use the id set in a config file



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/orange-more/administration/middleware/access_control.rb', line 18

def init(opts = {})
  defs = {:locked => [:preview, :admin, :orange], :login => '/login', :logout => '/logout',
          :handle_login => true, :openid => true, :single_user => false}
  opts = opts.with_defaults!(defs)
  @openid = opts[:openid]
  @locked = opts[:locked]
  @login = opts[:login]
  @logout = opts[:logout]
  @handle = opts[:handle_login]
  @single = opts[:single_user]
  unless @single
    orange.load(Orange::UserResource.new, :users)
  end
end

#need_to_handle?(packet) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/orange-more/administration/middleware/access_control.rb', line 78

def need_to_handle?(packet)
  @handle && ([@login, @logout].include? packet.request.path.gsub(/\/$/, ''))
end

#packet_call(packet) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/orange-more/administration/middleware/access_control.rb', line 33

def packet_call(packet)
  packet['user.id'] ||= (packet.session['user.id'] || false)
  packet['user'] = orange[:users].user_for(packet) unless packet['user.id'].blank?
  if @openid && need_to_handle?(packet)
    ret = handle_openid(packet)
    return ret unless ret.blank? # unless handle_openid returns false, exit immediately
  end
  unless access_allowed?(packet)
    if packet['user'] && packet['route.context'] == :admin
      # User doesn't have permissions, try to get to a site that he does
      site = packet['user'].orange_sites.first
      if site.class.to_s == "OrangeSubsite" 
        subsite = orange[:sitemap].url_for(packet, {:resource => 'subsites', :resource_id => site.id})
        packet.reroute("/admin#{subsite}#{packet['route.path'].gsub(/^\//, '')}")
      end
    end
    packet.flash['user.after_login'] = packet.request.path
    packet.reroute(@login)
  end
  
  pass packet
end