Authentication with Rails and RFM.

81 views
Skip to first unread message

Trym Valebjørg

unread,
Apr 30, 2013, 11:12:39 AM4/30/13
to rfmcom...@googlegroups.com
I'm trying to include a simple user authentication into my application, based on a filemaker database (using the ginjo-rfm gem). After getting some ideas from Ryan Bates' Authentication from Scratch, I've written a customized version of it, but running into some problems. I want to base my authentication on username and password allready stored in the FM-database. Password will be saved in full-text, no worries, this is absolutely OK for it's use.

When I submit my login form, I'm presented with 

> undefined method `find_by_username' for User:Class


User.rb
    class User < Rfm::Base
      include ActiveModel::SecurePassword
      include ActiveModel::MassAssignmentSecurity
      has_secure_password
      attr_accessible :username, :password
      
       config :layout => 'web__SupplierContacts'
    
      def self.authenticate(username, password)
        user = find_by_username(username)
        if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
          user
        else
          nil
        end
      end  
    
    end

sessions_controller.rb

    class SessionsController < ApplicationController
     def new
     end
     
     def create
       user = User.authenticate(params[:username], params[:password])
          if user && user.authenticate(params[:password])
         session[:user_id] = user.id
         redirect_to root_url, notice: "Logged in!"
       else
         flash.now.alert = "Email or password is invalid"
         render "new"
       end
     end
     
     def destroy
       session[:user_id] = nil
       redirect_to root_url, notice: "Logged out!"
     end
    end

I'm guessing this is a problem with my model inheriting from Rfm::Base, but I'm not sure. Any ideas?
Is there any way to rephrase the `Class.find_by_column` statement? I'm not able to do `User.where(:username => "username usernamerson"`, either (returns `undefined method 'where' for User:Class`).

This is obviously not working, since I'm writing this as done with ActiveRecord. Is there anyone who has done this? I'm utterly clueless. 

wbr

unread,
Jan 17, 2014, 8:37:22 PM1/17/14
to rfmcom...@googlegroups.com
Rfm layouts & models do not have the same functionality and syntax as ActiveRecord. So find_by_* will not work (unless you write your own methods to add this functionality). See the Rfm documentation for the required syntax of Rfm::Layout#find. The most basic Rfm find is just a hash.

    MyLayout.find :field_name=>"find request as string"

John Lannon

unread,
Jan 19, 2014, 1:49:56 PM1/19/14
to rfmcom...@googlegroups.com
It might be easier to approach this using pseudocode or to think about what you're trying to do at a higher level before writing any code or thinking much about implementation. 

  1. You have a table, web__SupplierContacts, that stores user's email addresses and passwords (in plain text). 
  2. You have a web application that requires users to authenticate against the web__SupplierContacts table
  3. If a user successfully authenticates, you want to store their user_id in a session
Since your passwords are stored in plain text (and this is okay for your use case), you don't need to worry about encryption. Instead you're going to check the user submitted password against the plaintext value stored in the database. So, you'll need to make some changes in your User model. Fortunately, the SessionsController won't need to change because the authentication details are encapsulated in your User model.

Here's some commented Rub that should work for your purposes:

class User < Rfm::Base
  #
  # you won't need the following module line because you're
  # passwords are not encrypted

  # include ActiveModel::SecurePassword

  # you won't need the following module because
  # you're not perfoming mass assingment, i.e.,
  # editing or creating anything in the
  # database, you're just finding a record and verifying
  # it's content
  # if you do plan to create or edit records using
  # your User model, you'll want to uncomment, but
  # for basic authentication, you won't need this.

  # include ActiveModel::MassAssignmentSecurity

  # you won't need the following because passwords
  # are not encrypted

  # has_secure_password

  # as mentioned above, you're not performing mass assignment
  # so you wont' need the following line

  # attr_accessible :username, :password

  config :layout => 'web__SupplierContacts'

  def self.authenticate(username, password)
    #
    # assuming the username field on your web__SupplierContacts
    # is called username.  othwerwise, change the hash key :username
    # to whatever the field name is on your layout
    #
    # Rfm's find method should return a ResultSet, which behaves
    # like an Array, so you can safely call the first method
    #
    user = find(:username => username).first
    if user && user.password == password
      user
    else
      nil
    end
  end

end

--
You received this message because you are subscribed to the Google Groups "RFM Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rfmcommunity...@googlegroups.com.
To post to this group, send email to rfmcom...@googlegroups.com.
Visit this group at http://groups.google.com/group/rfmcommunity?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages