How to create a separate admin interface for blogs in rails - ruby-on-rails

I need to create some routes for my blog website such that normal user can only read the posts and products. while super admin creates admins to moderate posts. How can i achieve that in rails?
I want
myapp.com/admin to bring me to log in page for admins.
Only super admin can manage moderators.
So far, I have a controller in 'app/controller/admin/home_controller'
which has index action for viewing all posts and users for admin.

Try adding a before filter before your action so that each time a admin try to hit that url he/she should get redirected to admin_login_url
before_filter :check_role
private
def check_role
unless current_user.role=='super_admin'
redirect_to admin_login_url
end
end

I am going to share what i actually did after reading tons of approaches just in case if anyone is stuck where i was. Hopefully helps:
Create a new controller in 'app/controllers/'. This controller is only responsible for GET requests.
Remove Create, Update, Delete methods from the controllers in 'app/controllers/', as these will be only accessible to admins.
Create a new admin_controller.rb in 'app/controllers/admin/'. Add authentications here.
Create new controllers(inherited from AdminsController) per model in the same directory and put the admin operations there.
class AdminPostsController < AdminsController

Related

How do you restrict access to a certain webpage?

I am trying to allow access to the log-in/sign-up page for a admin user only from my computer or any other way that lets me only see the web page for an admin sing-up-log-in.
Or what do typical web applications do to restrict access to the public towards a certain web page? If there is a bets-practice way, I would like to implement that.
I currently have Devise installed.
You can use the authenticate_user! Devise helper, adding it as callback within the needed controller and specifying the methods you want to control.
For instance if you have a Post model, then adding the authenticate_user! in the PostController it'll ask the user to be logged to have access to the methods in that specific controller:
class PostsController < ApplicationController
before_action :authenticate_user!
If you want to restrict just some specific methods then you can play with only and/or except.
See: Devise will create some helpers to use inside your controllers
and views. To set up a controller with user authentication, just add
this before_action (assuming your devise model is 'User')
Devise - Controller filters and helpers
According to your comment then you can create a method in the ApplicationController in order to restrict all of your controllers and methods.
This way you can define an array of addresses, and if the remote_ip coming from the request is in the array then you give access, if isn't then perform any other action:
ApplicationController < ActionController::Base
before_action :protect
private
def protect
addresses = ['127.0.0.1', ...]
if addresses.include?(request.remote_ip)
# give access
else
# restrict access
end
end
end
But if you need something more sophisticated then you'd have to see on your Nginx or Apache, whatever you're using to deploy your project.
I normally restrict webpage access through controller methods. My recent use case was going to a webpage only when payment was successful but redirecting when it was not, if any body issued a get request for that page directly, it would result in 404.
In your case, there can be multiple option for setup.
You can use cookies to see users credentials using Action Dispatcher
Use Devise for users and then you can fix a certain role to a user through adding a new migration and assign roles yourself after registering or let them choose.
I will expect you followed Devise route. In the controller action check for current user's role.
If User Not signed in (using current_user == nil)
redirect to home page and then return
else
if
its admin you go ahead and use the success page as partial and let them see the page using `<%= render 'pages/mypage'%>` and use return to end
else
just redirect back to home page with a notice "Don't try this".
redirect_to root_path, notice: 'Don't try this' and then use
return to end
end
(Just for fun, to see how many times a user did this wrong action, you can also have a table which stores current_user and number_of_wrong_attempt, and store their email whenever they try to go that page without permission before redirect in controller. After that you can email them with a background rake task which checks for a certain false attempt threshold that: "Hey! Your registration is being removed because you are doing unprohibited actions")

Admin vs non-admin controllers

So I recognize that Rails is a pretty opinionated language... which is why I feel like there's a definite Rails answer to this question. I'm trying to write the routing/ controllers for the following ADMIN user flow:
admin reviews/updates orders (has a get and post)
admin reviews/updates items in orders (has a get and post)
admin approves items in orders (has a get and post)
admin approves orders (has a get and post)
(Approval is not the same as update in this circumstance, so it's fairly important to differentiate that well)
This is literally a 1-2-3-4 step process flow, so I'm frankly thinking of doing everything under an AdminsController, with methods that follow the flow:
def step_1_get
orders_to_show = Order.where(...)
end
def step_1_post
order_params =
# some kind of order update
end
def step_2_get
items_to_show = Item.where(...)
end
def step_2_post
end
...
Similarly, I'd have all the views organized in steps under the admin folder.
I feel this would be much more clear than having a bunch of methods littered through the OrdersController and ItemsController even though I'm kind of breaking MVC. But again, what's the Railsy way of doing this?

Rails way to create several "create" pages

I have an "admin control panel" page which is handled by an AdminController. You can do two things in the control panel: create_product and create_order. There will be forms for each object, and when you submit the form, it will insert new records into the database.
What is the Rails way for implementing this? Do I generate a CreateProductController and CreateOrderController along with the appropriate view, which are accessible by clicking on the create_product and create_order links from the control panel?
Does the Rails way describe a way to handle both workflows using a single controller? At some point I will need to define a post method for each form, so it seems like creating separate controllers is the easiest way to set up required behavior and also the routing details.
Product and Order are all resources when having controller. The better way is to use RESTful resources. You can also add namespace for easier identification.
class Admin::ProductsController < AdminController
def create
end
def new
end
# And #show, #index, #destroy etc.
end
class Admin::OrdersController < AdminController
def create
end
def new
end
end

Rails routes - using associated model attribute as route root

I have a user that signs up and logs in.
Right now their route is rails standard "user/3".
A user belongs to an organization. An org has many users.
I want all users for that org, when they sign in, to have the url http://mysite.com/:organization name.
How would I accomplish this?
I'm not sure how your authentication is setup or what you're using to handle your authentication, but presumably when a user logs in successfully you just change the redirection in your log in action. Something like:
redirect_to user.organization
instead of redirect_to user
You need to browse on nested resources. Please look at http://guides.rubyonrails.org/routing.html#nested-resources
UPDATE: more appropriate answer
I think this is more for your scenario http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-scope
You have to do something like this...
First add a method to your organization model to show name instead of id in url
def to_param
name
end
and update your routes as required, and functionality also to show the users of that organization
Organization Controller..
def show
#organization = Organization.find(params[:organization])
#users = #organization.users
end
Redirect user to user organization show path after login.

Redirect users by the tables that they belong to

I have two tables: workers_table and admins_table.
I have two controllers and I use devise (sign_in, sign_up...).
I use:
before_filter :authenticate_user!
in the controllers of workers and admins.
assume I have the email of the user that signed in:
#email = current_user.email
I want to check where #email is found:
if it's found in the workers table, so redirect him to the index.html.erb of workers (and he can't enter to index.html.erb of the admins).
if it's found in the admins table, so redirect him to the index.html.erb of admins (and he can't enter to index.html.erb of the workers).
I know how to check if the user belongs to workers_table or admins_table.
But where should I check which table the user belongs to? should I define another controller?
Please guide me.
application_controller.rb would be a good place to define the authenticate_user functionality
another place could be a sessions_controller.rb if you have it
at the very least you could have an ensure_admin method for your admins_controller to add to the before_filter, and if they are not an admine, you could redirect_to workers#index
I'm new to rails, so i'm unsure as to the conventional way to do this, but the above is how I might do it.

Resources