Topic: HOW TO - Restrict Access to tables....

Here is a question that has still been left unresolved for me..

I am trying to build an online diary for students to enter their information for grade tracking and calculation. This is my second RoR app, but only the first for user login systems and an attempt at restricting access.

Put simply, I am trying to create a table for a user login system, stored in a table called 'users'.
Then I want another table for the student (once logged in) to add diary entries and after data has been gathered, he can research his grades from this diary.

My question is this -

Can you restrict access to users so that they can ONLY view their specific diary entries in the main database, or do I have to create a new table for every student?  If so, how would I do that???  Keep in mind this could span a few hundred students or more.

Any insight to this topic would be great, as I am struggling with this and can't seem to find the answers in any material I have seen so far.

"There are 10 people in this world, those who understand binary, and those who don't"

Re: HOW TO - Restrict Access to tables....

place something like this in the application.rb
   

    def check
        if i_own_this
            proceed to action or return true
        else
            redirect somewhere
        end
    end

then in your other controllers
    before_filter :check

Last edited by ajibanda (2009-02-08 21:39:19)

Re: HOW TO - Restrict Access to tables....

Wouldn't you just simply have a column on your diary entries table that indicates the user ID? If you set up your models so that you had:

  class User < ActiveRecord::Base
    has_many :diary_entries
  end
  class DiaryEntry < ActiveRecord::Base
    belongs_to :user
  end

When you log the user in you can store their user ID in the session:
  session[:user_id] = user_id_from_somewhere

then to get all the diary entries for the user you can:
  user = User.find(session[:user_id])
  entries = user.diary_entries

Re: HOW TO - Restrict Access to tables....

Yes, my current database has two tables - one is to store login information, the table looks like this:

Table Name = users

sid - string  (this means 'student id')
first_name - string
last_name - string
password - string
email - string
created_at - timestamp
updated_at - timestamp


My table for the actual information looks like this:

Table Name = diarys

sid - string
entry_day - datetime
grade1 - float(4,2)
grade2 - float(4,2)
''......"
grade8 - float(4,2)
diary_text - string

In my model for user and diary (after using the scaffold command) I used this:

User.rb

has_many :diarys

Diary.rb
belongs_to :user

I am still trying to figure out how to keep the users table out of the public eye in order to store the passwords, usernames and emails.
I also am trying to figure out how to log users in and keep that 'sid' as some sort of filter for the access to the tables.

I am still working on it and researching what you suggested here, would it help if I posted all my code I currently have, and you can make suggestions to it that way?

Thanks for the post    smile

"There are 10 people in this world, those who understand binary, and those who don't"

Re: HOW TO - Restrict Access to tables....

Well this is turning more into a database question smile

KZeeSoft wrote:

Yes, my current database has two tables - one is to store login information, the table looks like this:

Table Name = users

sid - string  (this means 'student id')
...

Your sid: is this something you're generating? Rails by defualt creates an id column. The only reason I can think of to create your own ID is because you want something specially-formatted. Like if you had a student in 2nd Grade and they were the 167th to sign up then you might create "G2-167". Otherwise the id column should be unique.

KZeeSoft wrote:

My table for the actual information looks like this:

Table Name = diarys

sid - string
...
diary_text - string

Are you using the sid to relate each of them? The thing is, Rails' ActiveRecord also helps you out if you name your columns in the right pattern. That is, you can define your diarys table as:

create_table :diaries, :force => true do |t|
  t.references :users
  ...etc...
  t.text diary_text

Notes: You can spell the plural of diary as "diaries" or probably better "diary_entries". Also, diary_text should be a "text" type, not "string", because "strings" turn into a 255-character-maximum field whereas "text" turns into a text string that apparently for MyISAM databases is 65K characters or on InnoDB tables is about 8K.  (See http://dev.mysql.com/doc/refman/5.1/en/ … ions.html) If it's a long diary you probably want "longtext" as the type instead.

Don't put an "sid" in there. Rails will automatically generate your foreign key as "user_id".

I'm not sure why the IDs and whatnot would be exposed though. Are you using a scaffold that just puts all of your ID info right out there? You should be able to just make a bunch of views and expose the fields you want.

Re: HOW TO - Restrict Access to tables....

OK, I am making progress on this and appreciate all your help smile

I redesigned the app from scratch, made a whole new scaffold, and inputted your suggestion of using this in my migration for create_diary_entries.rb file.

class CreateDiary_Entries < ActiveRecord::Migration
  def self.up
    create_table :diary_entries do |t|
      t.references :users
      t.datetime :diary_date
      t.float :class1_grade
      t.float :class2_grade
      t.float :gpa
 
      t.text :diary_text

      t.timestamps
    end
  end

  def self.down
    drop_table :diary_entries
  end
end


OK, so I have that part down, and my create_users.rb migration looks like this since I used the RESTful authentication plugin:

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table "users", :force => true do |t|
      t.column :login,                     :string
      t.column :email,                     :string
      t.column :crypted_password,          :string, :limit => 40
      t.column :salt,                      :string, :limit => 40
      t.column :created_at,                :datetime
      t.column :updated_at,                :datetime
      t.column :remember_token,            :string
      t.column :remember_token_expires_at, :datetime
     
     
    end
  end

  def self.down
    drop_table "users"
  end
end


In your opinion, what is the best way to allow users who are logged in to view their diary entries, ONLY THOSE DIARY ENTRIES that THEY created?

At the present time, I can still see everyone's entries and when I try to implement your classes in my viewer_controller, like the

    def check
     if i_own_this
        @user = User.find(session[:user_id])
        entries = user.diary_entries
     else
       render => login_path
     end
   end

I get tons of errors, and I am still stuck.

Any help?

"There are 10 people in this world, those who understand binary, and those who don't"

Re: HOW TO - Restrict Access to tables....

def diary_owner?(diary)
  @diaries = current_user.diaries
 
  unless @diaries.include?(diary)
    flash[:alert] = "This diary entry does not belong to you.
    redirect_to user_diaries_path
  end
end

Can't remember exactly how I did but something like that and a before_filter in the controller. Currently on a non-dev machine away from home.

Last edited by Aerpe (2009-02-12 10:24:24)

Re: HOW TO - Restrict Access to tables....

To be more specific on the problem I am having now:

In my diary_entries table, the "users_id" column is always a value of NULL, it will not populate when I create a new diary entry.

In my create_diary_entries.rb file, I have added this code, and reran the rake db:migrate

t.references :users

and in my User.rb Model, I have included:

has_many :diary_entries

and in my diary_entries.rb model, I have included:

belongs_to :user

When I try to call in diary entries for that user who is logged in via the restful_autentication plugin using this code:

<% for diary_entry in @diary_entries %>
  <tr>
     <td><%=h diary_entry.diary_date(@current_user)<td/>
     <td><%=h diary_entry.diary_text(@current_user)<td/>
     <td><%=h diary_entry.gpa(@current_user)<td/>
  <tr>

I also tried using the listed before_filters that were suggested, but I always got the red box new to Rails 2.3 that doesnt give you much error reporting, and even after looking through firebug and the mongrel server log, I can't seem to get the problem fixed.

Tell me which files you need me to post completely if you need them as I will gladly do so.

As always, I am humbly grateful to those who are a big help so far  = )

"There are 10 people in this world, those who understand binary, and those who don't"

Re: HOW TO - Restrict Access to tables....

Change

  t.references :users

to
  t.references :user

And an update on how I useally check if a user has access to a model. This is prolly not exactly what you need but should give you a better clue.

app/controllers/application.rb
include DiarySystem

app/controllers/diaries_controller.rb
before_filter :authorize_writer, :except => [:index, :new, :create]

lib/diary_system.rb
module DiarySystem
 
  protected # Dunno if this is needed
 
  def authorize_writer
    unless writer_has_key?
      flash[:alert] = "You're not allowed to access this diary."
      redirect_to user_diaries_path
    end
  end
 
  def writer_has_key?
    diary = Diary.find(params[:diary_id] || params[:id])
    current_user.diaries.include?(diary)
  end
end

Last edited by Aerpe (2009-02-13 21:25:31)