allow anonymous viewing of features
[opensuse:openfate.git] / app / controllers / application.rb
1 # Filters added to this controller apply to all controllers in the application.
2 # Likewise, all the methods added will be available for all controllers.
3
4 class ApplicationController < ActionController::Base
5   include ExceptionNotifiable
6   helper :all # include all helpers, all the time
7   before_filter :set_return_to, :init_user, :determine_client
8
9
10   def init_user
11     if (!CONFIG['user']['user_id'].nil?)
12       userid = CONFIG['user']['user_id']
13       logger.info "Debug mode, using userdata from config (#{userid}) for " + @return_to
14     elsif (!request.headers['HTTP_X_USERNAME'].nil?)
15       userid = request.headers['HTTP_X_USERNAME']
16       logger.info "iChain authenticated access (#{userid}) to " + @return_to
17       ichain_secret = request.headers['HTTP_X_OPENSUSE_DATA']
18       if (CONFIG['ichain']['secret'] != ichain_secret)
19         logger.error "iChain secret mismatch: #{ichain_secret} "
20         ExceptionNotifier.deliver_exception_notification("iChain secret mismatch: #{ichain_secret} ", self, request, {})
21         render_error :message => "Authentication error.", :status => 401
22       end 
23     else 
24       logger.info "Anonymous access to " + @return_to
25     end
26
27     if (userid.nil?)
28       session[:user] = User.new
29       session[:user].uid = 'openfate'
30       session[:user].organization = 'openSUSE.org'
31       session[:user].isAdmin = false
32       session[:user].isMember= false
33       session[:user].isAuthenticated= false
34     elsif( session[:user].nil? || session[:user].uid != userid) then
35       if (( session[:user] = User.find_by_uid(userid) ).nil?)
36         session[:user] = User.new
37         session[:user].uid = userid
38         session[:user].organization = 'openSUSE.org'
39         session[:user].isAdmin = false
40         session[:user].isMember= false
41       end
42       session[:user].isAuthenticated = true 
43       session.model.user_id = session[:user].uid
44       load_external_userdata( userid )
45       logger.info "Logged in user: #{session[:user].uid}, partner: #{session[:user].organization}"
46       if session[:editedFeatures].nil? then session[:editedFeatures] = Hash.new end
47     end
48   end
49
50
51   def require_auth
52     if (!session[:user].isAuthenticated)
53       render :template => "main/show_login_form"
54     end
55   end
56   
57   
58   # load extended user attributes from users.opensuse.org
59   def load_external_userdata( userid )
60     uri = URI.parse("http://users.opensuse.org/show/#{CGI::escape(userid)}.xml")
61     request = Net::HTTP::Get.new(uri.path)
62     request.add_field('x-username', userid)
63     logger.info "Loading users.o.o userdata for: #{userid}"
64     begin
65       Net::HTTP.start(uri.host, uri.port) do |http| 
66         http.read_timeout = 5
67         response = http.request(request)
68         unless( response.is_a? Net::HTTPSuccess )
69           logger.error "users returned '#{response.code}', message: \n#{response.body}"
70         else
71         rootNode = XML::Smart.string(response.body).root
72         session[:user].fullName = rootNode.find("/user/fullname").first.to_s
73         session[:user].email = rootNode.find("/user/email").first.to_s
74         if (rootNode.find("/user/member").length == 1) then session[:user].isMember = true end
75         end
76       end
77     rescue Exception => e
78       logger.error "Error while loading from users.o.o '#{uri}': " + e.to_s
79     end
80   end
81  
82    
83   def determine_client
84     $CLIENT = 'openFATE'
85     if request.request_uri.downcase.include? "partnerfate" then
86       $CLIENT = 'Partnerfate'
87     elsif request.request_uri.downcase.include? "ideas" then
88       $CLIENT = 'Ideas'
89     end
90     logger.debug "Client: #{$CLIENT}"
91   end
92   
93   
94   def requireAdminUser
95     if !(session[:user] && session[:user].isAdmin) then
96       render_error :message => "Unauthorized access", :status => 401
97     end
98   end
99
100
101   def set_return_to
102     @return_to = "https://" + request.host  + request.env['REQUEST_URI']
103   end
104
105
106   def render_error( opt={} )
107     @message = opt[:message] || "No message set"
108     @exception = opt[:exception]
109     @status = opt[:status] || 400
110     logger.error "ERROR: #{@status} #{@message}"
111     render :template => 'main/error'
112   end
113
114
115   def isOpenFate
116     return $CLIENT == "openFATE"
117   end
118
119
120   def isPartnerFate
121     return $CLIENT == "Partnerfate"
122   end
123
124
125   def isIdeas
126     return $CLIENT == "Ideas"
127   end
128   
129   
130   def feature_type_filter
131     # Filter for features in openFATE/Partnerfate and for ideas in Ideas mode
132     if (isOpenFate || isPartnerFate) then
133       return "not (@type = 'idea' or @type = 'requirement')"
134     elsif isIdeas
135       return "(@type = 'idea')"
136     end
137   end
138   
139   
140   def extract_errormessage( xml )
141     xml =~ /<k:x-sx-errormessage>([^<]+)/
142     if ($1) then return $1.strip
143       else return xml
144     end
145   end
146
147
148   def extract_errorcode( xml )
149     xml =~ /<k:x-sx-errorcode>([^<]+)/
150     if ($1) then return $1.strip
151       else return 0
152     end
153   end
154
155
156   # load feature either from keeper or from session if it 
157   # is unsaved. It is stored as string in the session because 
158   # XML::Smart cannot serialize.
159   def get_feature
160     if params[:id].nil? then
161       render_error( :message => "Invalid feature id." )
162     elsif !session[:editedFeatures].has_key?(params[:id]) then
163       @feature = Feature.loadFeature( params[:id], session[:user] )
164     else
165       @feature = Feature.new
166       @feature.xml = XML::Smart.string(session[:editedFeatures][params[:id]])
167       @feature.setModified(true)
168     end
169   end
170
171
172   # See ActionController::RequestForgeryProtection for details
173   # Uncomment the :secret if you're not using the cookie session store
174   protect_from_forgery :secret => 'ee4086ce6f157e0435b6d141a38a9927'
175 end