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



63
64
65
# File 'app/controllers/auth/concerns/omni_concern.rb', line 63

def after_omniauth_failure_path_for(scope)
  new_session_path(scope)
end

#failed_strategyObject



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

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

#failureObject



33
34
35
36
37
38
39
40
41
# File 'app/controllers/auth/concerns/omni_concern.rb', line 33

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



54
55
56
57
58
59
60
61
# File 'app/controllers/auth/concerns/omni_concern.rb', line 54

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



44
45
46
# File 'app/controllers/auth/concerns/omni_concern.rb', line 44

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.



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
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
# File 'app/controllers/auth/concerns/omni_concern.rb', line 129

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
         
          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



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

def omniauth_failed_path_for(res)
  omniauth_failure_path(res)
end

#passthruObject



29
30
31
# File 'app/controllers/auth/concerns/omni_concern.rb', line 29

def passthru
  
end

#set_devise_mapping_for_omniauthObject



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'app/controllers/auth/concerns/omni_concern.rb', line 15

def set_devise_mapping_for_omniauth
  model = nil
  if !request.env["omniauth.model"].blank?
    puts "the request env is:"
    puts request.env["omniauth.model"]
    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



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

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



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/controllers/auth/concerns/omni_concern.rb', line 88

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



77
78
79
80
81
82
83
84
# File 'app/controllers/auth/concerns/omni_concern.rb', line 77

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