Jump to content

The ultimate community for Ruby on Rails developers.


Photo

Authorization Rails 4 with Devise

devise authorization

  • Please log in to reply
5 replies to this topic

#1 vikhyat620

vikhyat620

    Passenger

  • Members
  • 9 posts

Posted 07 May 2014 - 04:00 PM

I made a post model along with its generated controller, but anyone can Edit and Destroy the posts. How can i allow only the author to edit and destroy the post. I tried something like this but it failed.

 

rails g add_user_name_to_posts username:string

 

I added the necessary column and made it a hidden field.

In the controller:

@post.username = current_user.user_name

 

I made a custom field for that in devise.

So the posts automatically get a username filled out

 

In my views i added:

<% if @post.username = current_user.user_name %>

(the links to edit and destroy)

<% end %>

 

Note.The method is called username for posts, but user_name for the user.

 

Please tell me why this failed and how i can avtually achieve what im going for.



#2 Jamie

Jamie

    Controller

  • Moderators
  • 140 posts
  • LocationNewcastle, UK

Posted 07 May 2014 - 04:28 PM

Hi

 

Firstly, I wouldn't be using hidden fields in your views unless it's absolutely necessary. It will open up a huge can of worms and security issues.

 

You want to be making relationships between the models you already have.

 

For example, a User has_many :posts and a Post belongs_to :user

 

Once that's done, you can then create new posts by calling current_user.posts.new(post_params) etc..

 

As for checking in the controller if could create something like this...

def destroy
  if current_user == @post.user
    @post.destroy
  else
    redirect_to @post, error: "You don't have permission."
  end
end

And in the view you're almost correct but I'd again compare with the user object you already have...

<% if @post.user == current_user %>
  (the links to edit and destroy)
<% end %>

Notice the double equality comparison in the example above.

 

Hope this helps. Post the code to your app if you need further help!

 

 

JB


Rails developer based in Newcastle, UK.


#3 vikhyat620

vikhyat620

    Passenger

  • Members
  • 9 posts

Posted 08 May 2014 - 04:11 AM

I got a nomethod error on the posts index.

Here is my user.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable


  has_many :posts 
   validates :first_name, presence: true
   validates :last_name, presence: true
   validates :user_name, presence: true,  format: {
                            with: /\A[a-zA-Z0-9_-]+\Z/,
                            message: 'must be formatted correctly.'
                           }
end

post.rb

class Post < ActiveRecord::Base
belongs_to :user
end

post-controller:

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]


  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end


  # GET /posts/1
  # GET /posts/1.json
  def show
  end


  # GET /posts/new
  def new
    @post = Post.new
  end


  # GET /posts/1/edit
  def edit
  end


  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)
    @post.name = current_user.first_name + " " +current_user.last_name
    @post.username = current_user.user_name


    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render action: 'show', status: :created, location: @post }
      else
        format.html { render action: 'new' }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end


  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Post was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end


  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
     if current_user == @post.user
    @post.destroy
  else
    redirect_to @post, error: "You don't have permission."
  end
    respond_to do |format|
      format.html { redirect_to posts_url }
      format.json { head :no_content }
    end
  end


  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end


    # Never trust parameters from the scary internet, only allow the white list through.
    def post_params
      params.require(:post).permit(:name, :content)
    end
end




If u want any files, ill upload them. Sorry for being such a noob in rails -_-



#4 Jamie

Jamie

    Controller

  • Moderators
  • 140 posts
  • LocationNewcastle, UK

Posted 08 May 2014 - 07:58 AM

Hi

 

As I mentioned above, you don't want to be saving the first, last and usernames to the post. But you want to add a user_id column to the posts table, which is an integer.

 

Then you'd be able to do something like...

def create
    @post = current_user.posts.new(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render action: 'show', status: :created, location: @post }
      else
        format.html { render action: 'new' }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

Rails developer based in Newcastle, UK.


#5 vikhyat620

vikhyat620

    Passenger

  • Members
  • 9 posts

Posted 08 May 2014 - 02:26 PM

So, should I create a migration, and remove those columns? I'll add the user_id:integer field and define it as:
Post.user_id = current_user.id

I guess that's right, as well as the line u added in def create.

In the views id add:
<% if current_user.id = post.user_id %>
<% end %>

Is this right? I use devise

#6 vikhyat620

vikhyat620

    Passenger

  • Members
  • 9 posts

Posted 08 May 2014 - 02:38 PM

I was scrolling through a few apps on GitHub and I saw This in the model:
tracked owner: ->(controller, model) { controller && controller.current_user }

In the controller:


@post.user = current_user


The migration has a user_id, but the above line has the method .user, kinda confused about that.





Also tagged with one or more of these keywords: devise, authorization

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users