66require "methodchain"
77require "nokogiri"
88require "open-uri"
9- require "openid"
10- require "openid/extensions/ax"
11- require "openid/store/filesystem"
129require "pinion"
1310require "pinion/sinatra_helpers"
1411require "redcarpet"
2522require "lib/git_diff_utils"
2623require "lib/keyboard_shortcuts"
2724require "lib/meta_repo"
25+ require "lib/openid_provider"
2826require "lib/pretty_date"
2927require "lib/script_environment"
3028require "lib/stats"
3937require "resque_jobs/deliver_review_request_emails.rb"
4038
4139NODE_MODULES_BIN_PATH = "./node_modules/.bin"
42- OPENID_AX_EMAIL_SCHEMA = "http://axschema.org/contact/email"
4340UNAUTHENTICATED_ROUTES = [ "/signin" , "/signout" , "/inspire" , "/statusz" , "/api/" ]
4441# NOTE(philc): Currently we let you see previews of individual commits and the code review stats without
45- # being logged in, as a friendly UX. When we flesh out our auth model, we should intentionally make this
46- # configurable.
42+ # being logged in, as a friendly UX. When we flesh out our authorization model, we should intentionally make
43+ # this configurable.
4744UNAUTHENTICATED_PREVIEW_ROUTES = [ "/commits/" , "/stats" ]
4845
49-
50- # OPENID_PROVIDERS is a string env variable. It's a comma-separated list of OpenID providers.
51- OPENID_PROVIDERS_ARRAY = OPENID_PROVIDERS . split ( "," )
52-
5346class BarkeepServer < Sinatra ::Base
5447 attr_accessor :current_user
5548
@@ -106,8 +99,6 @@ class BarkeepServer < Sinatra::Base
10699 # Session hijacking protection breaks Chrome sessions and offers little protection anyway
107100 set :protection , except : :session_hijacking
108101
109- raise "You must have an OpenID provider defined in OPENID_PROVIDERS." if OPENID_PROVIDERS . empty?
110-
111102 configure :development do
112103 STDOUT . sync = true # Flush any output right away when running via Foreman.
113104 enable :logging
@@ -145,6 +136,11 @@ class BarkeepServer < Sinatra::Base
145136 GitDiffUtils . setup ( RedisManager . redis_instance )
146137 end
147138
139+ # Register the authentication provider specified by AUTHENTICATION_PROTOCOL.
140+ AUTHENTICATION_PROVIDERS = { "openid" => OpenidProvider }
141+ authentication_provider = AUTHENTICATION_PROVIDERS [ AUTHENTICATION_PROTOCOL ]
142+ register authentication_provider
143+
148144 helpers do
149145 def current_page_if_url ( text ) request . url . include? ( text ) ? "currentPage" : "" end
150146
@@ -200,9 +196,7 @@ def ensure_required_params(*required_params)
200196
201197 # Save url to return to it after login completes.
202198 session [ :login_started_url ] = request . url
203- redirect ( OPENID_PROVIDERS_ARRAY . size == 1 ?
204- get_openid_login_redirect ( OPENID_PROVIDERS_ARRAY . first ) :
205- "/signin/select_openid_provider" )
199+ redirect authentication_provider ::signin_url ( request , session )
206200 end
207201 end
208202
@@ -213,49 +207,7 @@ def ensure_required_params(*required_params)
213207 get "/signin" do
214208 session . clear
215209 session [ :login_started_url ] = request . referrer
216- redirect ( OPENID_PROVIDERS_ARRAY . size == 1 ?
217- get_openid_login_redirect ( OPENID_PROVIDERS_ARRAY . first ) :
218- "/signin/select_openid_provider" )
219- end
220-
221- get "/signin/select_openid_provider" do
222- erb :select_openid_provider , :locals => { :openid_providers => OPENID_PROVIDERS_ARRAY }
223- end
224-
225- # Users navigate to here from select_openid_provider.
226- # - provider_id: an integer indicating which provider from OPENID_PROVIDERS_ARRAY to use for authentication.
227- get "/signin/signin_using_openid_provider" do
228- provider = OPENID_PROVIDERS_ARRAY [ params [ :provider_id ] . to_i ]
229- halt 400 , "OpenID provider not found." unless provider
230- redirect get_openid_login_redirect ( provider )
231- end
232-
233- # Handle login complete from openid provider.
234- get "/signin/complete" do
235- @openid_consumer ||= OpenID ::Consumer . new ( session ,
236- OpenID ::Store ::Filesystem . new ( File . join ( File . dirname ( __FILE__ ) , "/tmp/openid" ) ) )
237- openid_response = @openid_consumer . complete ( params , request . url )
238- case openid_response . status
239- when OpenID ::Consumer ::FAILURE
240- "Sorry, we could not authenticate you with this identifier. #{ openid_response . display_identifier } "
241- when OpenID ::Consumer ::SETUP_NEEDED then "Immediate request failed - Setup Needed"
242- when OpenID ::Consumer ::CANCEL then "Login cancelled."
243- when OpenID ::Consumer ::SUCCESS
244- ax_resp = OpenID ::AX ::FetchResponse . from_success_response ( openid_response )
245- email = ax_resp [ "http://axschema.org/contact/email" ] [ 0 ]
246- if defined? ( PERMITTED_USERS ) && !PERMITTED_USERS . empty?
247- unless PERMITTED_USERS . split ( "," ) . map ( &:strip ) . include? ( email )
248- halt 401 , "Your email #{ email } is not authorized to login to Barkeep."
249- end
250- end
251- session [ :email ] = email
252- unless User . find ( :email => email )
253- # If there are no admin users yet, make the first user to log in the first admin.
254- permission = User . find ( :permission => "admin" ) . nil? ? "admin" : "normal"
255- User . new ( :email => email , :name => email , :permission => permission ) . save
256- end
257- redirect session [ :login_started_url ] || "/"
258- end
210+ redirect authentication_provider ::signin_url ( request , session )
259211 end
260212
261213 get "/signout" do
@@ -561,26 +513,6 @@ def ensure_required_params(*required_params)
561513
562514 def logged_in? ( ) current_user && !current_user . demo? end
563515
564- # Construct redirect url to google openid.
565- def get_openid_login_redirect ( openid_provider_url )
566- @openid_consumer ||= OpenID ::Consumer . new ( session ,
567- OpenID ::Store ::Filesystem . new ( File . join ( File . dirname ( __FILE__ ) , "/tmp/openid" ) ) )
568- begin
569- service = OpenID ::OpenIDServiceEndpoint . from_op_endpoint_url ( openid_provider_url )
570- oidreq = @openid_consumer . begin_without_discovery ( service , false )
571- rescue OpenID ::DiscoveryFailure => why
572- "Could not contact #{ OPENID_DISCOVERY_ENDPOINT } . #{ why } "
573- else
574- ax_request = OpenID ::AX ::FetchRequest . new
575- # Information we require from the OpenID provider.
576- required_fields = [ "http://axschema.org/contact/email" ]
577- required_fields . each { |field | ax_request . add ( OpenID ::AX ::AttrInfo . new ( field , nil , true ) ) }
578- oidreq . add_extension ( ax_request )
579- host = "#{ request . scheme } ://#{ request . host_with_port } "
580- oidreq . redirect_url ( host , "#{ host } /signin/complete" )
581- end
582- end
583-
584516 def create_comment ( repo_name , sha , filename , line_number_string , text )
585517 commit = MetaRepo . instance . db_commit ( repo_name , sha )
586518 raise "No such commit." unless commit
0 commit comments