20da46732098dd0b87f699954a62caac98e2ec4c
[arvados.git] / app / controllers / user_sessions_controller.rb
1 class UserSessionsController < ApplicationController
2   before_filter :login_required, :only => [ :destroy ]
3
4   skip_before_filter :uncamelcase_params_hash_keys
5   skip_before_filter :find_object_by_uuid
6
7   respond_to :html
8
9   # omniauth callback method
10   def create
11     omniauth = env['omniauth.auth']
12     #logger.debug "+++ #{omniauth}"
13
14     identity_url_ok = (omniauth['info']['identity_url'].length > 0) rescue false
15     unless identity_url_ok
16       # Whoa. This should never happen.
17
18       @title = "UserSessionsController.create: omniauth object missing/invalid"
19       @body = "omniauth.pretty_inspect():\n\n#{omniauth.pretty_inspect()}"
20
21       view_context.fatal_error(@title,@body)
22       return redirect_to openid_login_error_url
23     end
24
25     user = User.find_by_identity_url(omniauth['info']['identity_url'])
26     if not user
27       # New user registration
28       user = User.create!(:email => omniauth['info']['email'],
29                           :first_name => omniauth['info']['first_name'],
30                           :last_name => omniauth['info']['last_name'],
31                           :identity_url => omniauth['info']['identity_url'])
32     else
33       user.email = omniauth['info']['email']
34       user.first_name = omniauth['info']['first_name']
35       user.last_name = omniauth['info']['last_name']
36       user.save
37     end
38
39     omniauth.delete('extra')
40
41     # Give the authenticated user a cookie for direct API access
42     session[:user_id] = user.id
43     session[:user_uuid] = user.uuid
44     session[:api_client_uuid] = nil
45     session[:api_client_trusted] = true # full permission to see user's secrets
46
47     @redirect_to = root_path
48     if session.has_key? :return_to
49       return send_api_token_to(session.delete :return_to)
50     end
51     redirect_to @redirect_to
52   end
53
54   # Omniauth failure callback
55   def failure
56     flash[:notice] = params[:message]
57   end
58
59   # logout - Clear our rack session BUT essentially redirect to the provider
60   # to clean up the Devise session from there too !
61   def logout
62     session[:user_id] = nil
63
64     flash[:notice] = 'You have logged off'
65     redirect_to "#{CUSTOM_PROVIDER_URL}/users/sign_out?redirect_uri=#{root_url}"
66   end
67
68   # login - Just bounce to /auth/joshid. The only purpose of this function is
69   # to save the redirect_to parameter (if it exists; see the application
70   # controller). /auth/joshid bypasses the application controller.
71   def login
72     if current_user and params[:return_to]
73       # Already logged in; just need to send a token to the requesting
74       # API client.
75       #
76       # FIXME: if current_user has never authorized this app before,
77       # ask for confirmation here!
78
79       send_api_token_to(params[:return_to])
80     else
81       # TODO: make joshid propagate return_to as a GET parameter, and
82       # use that GET parameter instead of session[] when redirecting
83       # in create().  Using session[] is inappropriate: completing a
84       # login in browser window A can cause a token to be sent to a
85       # different API client who has requested a token in window B.
86
87       session[:return_to] = params[:return_to]
88       redirect_to "/auth/joshid"
89     end
90   end
91
92   def send_api_token_to(callback_url)
93     # Give the API client a token for making API calls on behalf of
94     # the authenticated user
95
96     # Stub: automatically register all new API clients
97     api_client_url_prefix = callback_url.match(%r{^.*?://[^/]+})[0] + '/'
98     api_client = ApiClient.find_or_create_by_url_prefix(api_client_url_prefix)
99
100     api_client_auth = ApiClientAuthorization.
101       new(user: user,
102           api_client: api_client,
103           created_by_ip_address: Thread.current[:remote_ip])
104     api_client_auth.save!
105
106     if callback_url.index('?')
107       callback_url << '&'
108     else
109       callback_url << '?'
110     end
111     callback_url << 'api_token=' << api_client_auth.api_token
112     redirect_to callback_url
113   end
114 end