Module: Auth::Concerns::OmniConcern

Extended by:
ActiveSupport::Concern
Included in:
OmniauthCallbacksController
Defined in:
app/controllers/auth/concerns/omni_concern.rb

Instance Method Summary collapse

Instance Method Details

#after_omniauth_failure_path_for(scope) ⇒ Object



68
69
70
# File 'app/controllers/auth/concerns/omni_concern.rb', line 68

def after_omniauth_failure_path_for(scope)
  new_session_path(scope)
end

#failed_strategyObject



55
56
57
# File 'app/controllers/auth/concerns/omni_concern.rb', line 55

def failed_strategy
  request.respond_to?(:get_header) ? request.get_header("omniauth.error.strategy") : env["omniauth.error.strategy"]
end

#failureObject



38
39
40
41
42
43
44
45
46
# File 'app/controllers/auth/concerns/omni_concern.rb', line 38

def failure
  f = failure_message
  flash[:omniauth_error] = f.blank? ? notice : f
  respond_to do |format|
      format.json { render json: {"failure_message" => flash[:omniauth_error]}, status: :unprocessible_entity}
      format.html { render "auth/omniauth_callbacks/failure.html.erb" }
  end

end

#failure_messageObject



59
60
61
62
63
64
65
66
# File 'app/controllers/auth/concerns/omni_concern.rb', line 59

def failure_message
  exception = request.respond_to?(:get_header) ? request.get_header("omniauth.error") : env["omniauth.error"]
  error   = exception.error_reason if exception.respond_to?(:error_reason)
  error ||= exception.error        if exception.respond_to?(:error)
  error ||= (request.respond_to?(:get_header) ? request.get_header("omniauth.error.type") : env["omniauth.error.type"]).to_s

  error.to_s.humanize if error
end

#get_omni_hashObject



49
50
51
# File 'app/controllers/auth/concerns/omni_concern.rb', line 49

def get_omni_hash
  request.env["omniauth.auth"]
end

#omni_commonObject

Working: First searches for an account with the oauth identity. Found : tries to update it with a new access token, failing update -> retursn failure. Not Found : tries to create an account with the email of the oauth identity, and identities = [oauth_identity] if op_success : return success

elsif matched_count == 1 : it means an account already exists with this email . Here there are two possibilities.

  1. The earlier account was created by using another oauth provider -> in this case its version will have been set as ‘1’, and we now execute a versioned_update -> pushing in the identity of the other oauth account. Thus two oauth providers are merged into one if they share the same email address.

  2. the earlier account was created by the normal sign up process: in this case its version will be ‘0’, the versioned updated to push in the oauth identity will fail. If the earlier account is a confirmed account, error will say accoutn in user, if not, then error will say, “there was some errro…”

else there was no matched count, and op failed, so we return failure.

** To prevent oauth account merger, set the configuration option :prevent_oauth_merger to true, it is false by default.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'app/controllers/auth/concerns/omni_concern.rb', line 134

def omni_common
      
      success = false
      failure = false
      failure_message = "There was an error processing your request"

      begin
        
        model_class = request.env["devise.mapping"]
        if model_class.nil?
        
         redirect_to omniauth_failed_path_for("no_resource"), :notice => "No resource was specified in the omniauth callback request." and return 
        else
          resource_klazz = request.env["devise.mapping"].to
          
         # puts "request env."
         # puts request.env.to_s

          omni_hash = get_omni_hash
          
          puts "the omni hash is:"
          puts omni_hash
          
          identity = Auth::Identity.new.build_from_omnihash(omni_hash)

          ##this index is used for the first query during oauth, to check whether the user already has registered using oauth with us.
          puts "identity is:"
          puts identity
          existing_oauth_resources = 
          resource_klazz.collection.find(
            {"identities" =>
                   {"$elemMatch" => 
                          {"provider" => identity.provider, "uid" => identity.uid}
                   }
            })
            
         

          if existing_oauth_resources.count == 1
            
            puts "found matching identity."
              
            if  update_access_token_and_expires_at(existing_oauth_resources,resource_klazz,identity.attributes.except("_id","provider","uid"),identity.provider)
               puts "updated access token."     
               success = true
                #respond_with @resource, location: after_sign_in_path_for(@resource)               
            else
                puts "failed to update access token."
                success = false
              #redirect_to omniauth_failed_path_for(resource_klazz.name),:notice => "Failed to update the acceess token and token expires at"

            end

          
          elsif signed_in?

            puts("it is a current user trying to sign up with oauth.")
            
            (current_res)        

          else 
            
            puts("no such user exists, trying to create a new user by merging the fields.")
              
            @resource = resource_klazz.new
            @resource.email = identity.email
            @resource.password = Devise.friendly_token(20)
            @resource.regenerate_token
            @resource.identities = [identity.attributes.except("_id")]
            if @resource.respond_to?(:confirmed_at)
              @resource.confirmed_at = Time.now.utc  
            end
              
            ## skip_email_unique_validation is set to true in omni_concern in the situation:
            ##1.there is no user with the given identity.
            ## however it is possible that a user with this email exists.
            ## in that case, if we try to do versioned_create, then the prepare_insert block in mongoid_versioned_atomic, runs validations. these include, checking if the email is unique, and in this case, if a user with this email already exists, then the versioned_create doesnt happen at all. We don't want to first check if there is already an account with this email, and in another step then try to do a versioned_update, because in the time in between another user could be created. So instead we simply just set #skip_email_unique_validation to true, and as a result the unique validation is skipped.
            @resource.skip_email_unique_validation = true
            

            @resource.m_client = self.m_client
            
            ## end.
            @resource.versioned_create({"email" => @resource.email})
            ##reset so that no other issues crop up later.
            @resource.skip_email_unique_validation = false
            
            #puts "@resource email is:"
            #puts @resource.email.to_s              

            if @resource.op_success
              puts "create was successfull"
                 @resource
                puts "signed in resource."
                #respond_with @resource, location: after_sign_in_path_for(@resource)
                 success = true
                  #respond_to do |format|
                  #  format.html { redirect_to after_sign_in_path_for(@resource) and return}
                  #  format.json  { render json: @resource, status: :updated and return}
                  #end      
                  puts "came after the response."

              ##do the update.
            elsif @resource.matched_count == 1
                #puts "found such a resource."    
                
                ## this means a resource with this email account was found.
                ## if the account is not confirmed, then we can push the identity.
                ## and we can reset the password.

                @resource = resource_klazz.where(:email => @resource.email).first
                @resource.m_client = self.m_client
                
                if @resource.confirmed?
                  failure_message = "That email is in use by another account"
                end

                if Auth.configuration.prevent_oauth_merger == true

                  success = false
                  
                else

                  @resource.identities.push(identity.attributes.except("_id"))

                  @resource.versioned_update({"identities" => 1})

                  if @resource.op_success
                    puts "succeeded and signed in user."
                     @resource
                    
                    success = true

                    #respond_with @resource, location: after_sign_in_path_for(@resource)

                  else
                    puts "op success failure"
                    success = false
                    #redirect_to omniauth_failed_path_for(resource_klazz.name),:notice => "Failed to create new identity"
                  end

                end
             
            else
              
              puts "resource create failed."
              puts @resource.errors.full_messages.to_s
              success = false
              #redirect_to omniauth_failed_path_for(resource_klazz.name),:notice => "Failed to create new identity"
            end



          end

        end
            
      

      rescue => e
        puts "SOME OTHER ERROR"
        puts e.to_s
        puts e.backtrace
        redirect_to omniauth_failed_path_for("error"), :notice => "error" and return
        success = false
      end

      puts "Success is :#{success.to_s}"

      
        respond_to do |format|
          if success == true
            format.html { redirect_to (@resource) and return}
            format.json  { render json: @resource, status: :updated and return}
          else
            #@resource.errors.add(:_id,"failed")
            format.html { redirect_to omniauth_failed_path_for(failure_message), :notice => failure_message and return}
            format.json  { render json: {:errors => failure_message}, status: :unprocessible_entity and return}
          end
        end   
      

end

#omniauth_failed_path_for(res) ⇒ Object



72
73
74
# File 'app/controllers/auth/concerns/omni_concern.rb', line 72

def omniauth_failed_path_for(res)
  omniauth_failure_path(res)
end

#passthruObject



34
35
36
# File 'app/controllers/auth/concerns/omni_concern.rb', line 34

def passthru
  
end

#set_devise_mapping_for_omniauthObject



21
22
23
24
25
26
27
28
29
30
31
32
# File 'app/controllers/auth/concerns/omni_concern.rb', line 21

def set_devise_mapping_for_omniauth
  model = nil
  if !request.env["omniauth.model"].blank?
    
    request.env["omniauth.model"].scan(/omniauth\/(?<model>[a-zA-Z]+)\//) do |ll|
      jj = Regexp.last_match
      model = jj[:model]
    end
    model = model.singularize
    request.env["devise.mapping"] = Devise.mappings[model.to_sym]
  end
end

#translation_scopeObject



77
78
79
# File 'app/controllers/auth/concerns/omni_concern.rb', line 77

def translation_scope
  'devise.omniauth_callbacks'
end

#update_access_token_and_expires_at(existing_oauth_resources, resource_klazz, identity_info, provider) ⇒ Object

@return : true if the update was successfull, false otherwise method from_view is taken from Auth::ApplicationController



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/controllers/auth/concerns/omni_concern.rb', line 93

def update_access_token_and_expires_at(existing_oauth_resources,resource_klazz,identity_info,provider)
  @resource = from_view(existing_oauth_resources,resource_klazz)
  @resource.m_client = self.m_client
  ##identity_info should be a key -> value hash, 
  update_identity_information(identity_info,provider)

  @resource.versioned_update({"identities" => 1})

  if @resource.op_success
                                      
     @resource

    true
    
  else


    false

  end
end

#update_identity_information(identity_info, provider) ⇒ Object



82
83
84
85
86
87
88
89
# File 'app/controllers/auth/concerns/omni_concern.rb', line 82

def update_identity_information(identity_info,provider)
    @resource.identities.map{|i|
      if(i["provider"] && i["provider"] == provider)
        i["access_token"] = identity_info["access_token"]
        i["token_expires_at"] = identity_info["token_expires_at"]
      end
    }
end