Rails: How to link a model to an authenticated user - ruby-on-rails-3

I want to link a model Tasks to a User properly, to make sure that only an authenticated user can access only the Tasks and dependent models that belong_to User and Task
My user model was generated using nifty authentication from Railscasts' Ryan B
I'm having a lot of trouble finding a guide on how to set up these views to be secure.
Any suggestions SO?

I think you are looking for an authorization solution. If this is a simple app, you should set up your controllers to return only tasks belong to the user like so:
#tasks = current_user.tasks
Presumably you have a has_many association set up on your User model. If you do this for all your controllers, they will be scoped to your user, so you don't have to worry about authorization.
If you are looking for a more complex solution, look towards something like cancan.

Related

Strongloop/Loopback: How to login if multiple models extend built-in User model

I've just started to develop with Strongloop framework and I've seen that you can extend basic built-in models, such as the User model. E.g.: a Patient model may extend User model. Therefore, basic user information and services will be automatic extended from User model and it will be possible to request for login, logout etc. through the Patient model (e.g.: Patient.login(credentials)).
However, if I have multiple models that extend from User model (e.g.: Physicion, Admin and Patient), how to execute remote methods from the User model without knowing which one of the three models do I have to execute? For instance, if I have a Patient account, I can request Patient.login(credentials), and the Strongloop will make the login correctly. On the other hand, at the login page, I don't know if a Patient or a Physicion user has typed his/her credentials. So, I don't know which login method do I have to invoke: if Patient.login or Physicion.login. The remote method User.login does not work in my case. How to request for login without knowing the type of user beforehand?
If you are extending the User model, it shouldn't matter as they will all look for the same auth token in the DB and execute the same exact code in loopback/common/models/User.js, they will just be named differently.
But in the larger picture, you should keep track of what type of user you're dealing with by their identifying information (email etc) and not by the submodel/class of model they will be accessing. You should know this before you make the proper call.
Take a look at the Role model and RoleMapping model. You could for instance create Patient, Physician, and Admin Roles, and then map them to Users, then use a single model (User) for logging in.
What if you have a physician who is also a patient? Or a physician who is also an Admin? With roles you can manage this with a single User model, and then know which sub model to use.
Been working with IBM-StrongLoop Loopback 3 for a while now, decided to build up this starter for building multi-user models api. Do check it out.
Multi-User API Starter. It's absolutely free to use and also has been built to do all the heavy lifting for you.
All you need to do is to let your CustomUser Models i.e Patient, Doctor, Physician etc.. extend BaseUser which is present in the starter. For Role Based permission in ACL, you can check up on an example usage of the starter, Loopback Multi-User Based Auth and Role-Based ACL All that's all...

Create Custome Template in Devise and Rails4

I have devise with single table inheritance,
Class User
end
class a < user
end
class b < user
end
class c < user
end
I wanted sign_up page for each class a,b,c and sign_in page.
How to achieve in Devise!!!
How to create custom templates in user devise folder.
I am not sure about purposes you'd like to implement it to, but I think you should consider splitting your users' roles into separate models according to devise multiple models readme
and creating different views for them if you need it:
If you have more than one Devise model in your application (such as "User" and "Admin"), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set "config.scoped_views = true" inside "config/initializers/devise.rb".
After doing so, you will be able to have views based on the role like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new"
Keep in mind that those models will have completely different routes. They do not and cannot share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend you to use a role-based approach, by either providing a role column or using CanCan.

CakePHP: REST API Resources with Multiple Levels

I am trying to make a REST API with CakePHP but I'm not sure how to approach resources that are more than one level down. For example, I want to make my API so that when a client sends a get request to /users/1/friends.json, a JSON representation of that user's friends is returned. What would be the preferred way to approach this? Should I create a Friendships controller and model and reroute as necessary or perhaps keep everything in the users controller? Just want to know what the standard way of doing this is.
If you want to expose a lot of features like: creating/updating/deleting a user, getting a user, getting all users, etc. you end with a lot of methods in your controller.
I would suggest to use different controllers:
a UserController which owns CRUD methods related to a user, and a method to fetch all users. That would mean 5 methods in this controller;
a FriendController which owns all methods related to a friendship relation: getting user's friends but also creating/removing relations between two users.
I don't know CakePHP but I wrote something about Symfony2 REST APIs and my use case was a User API. You could pick ideas like how to manage friendship relations between users.

Mixing secured users and visitors on the same site

I suspect this is more a question of best practices than code. If I have a site (RoR3 and Devise) where a registered user can upload and create documents into a database with the normal collection of views. Of course the user must first sign up and log into the site. Having created a document they might want to send out a link to another person who is not registered with the site (and won't be).
So what I envision is a set of views that are "read only" if you will where the invited person can view the document but can't navigate outside that view, except for the home page. Devise doesn't seem to have the concept of a non logged in visitor that I can see and I haven't found anyone who has done this.
Thank you
Yeah, this can get tricky, especially if non-registered users can do some stuff but not all. We tried a couple of approaches to solve this problem in a company I recently worked for, including the invitations aspect you mentioned.
Because our entire app revolved around users, when a user visited the site, we created an instance of User. If the user was signed in the user model would be backed by a database record, and if not, they were just a virtual user and we used session data to store semi-persistent state information.
In application_controller we set current_user to either the real user or just an object, so it was always available, and quacked like a user, especially including a registered? method
At first we wrapped tons of stuff in our views with if current_user.registered? all over the place. But that quickly got to be a mess. The better pattern (in cases where the differences were significant) would be to create partials that like _sidebar and _sidebar_registered, so we could create a method that, given the root name of a partial rendered the appropriate one depending on user state.
In the case of invitations where users have limited access to content if they were invited, we wrote an invitation module that was backed by a model. The invitER could send an email from the system, or generate a URL with an embedded token. We stored the token in a table so we knew who invited whom, which was necessary in our case -- looking up the token was all that was needed to authenticate. Once the user was sorta-authenticated, we stored the state in the session, and a method on User (invited?) would let us know if the user had access.
In general there were certain whole controller actions that only registered users could get at (e.g. edit/delete) we would just use before_filters in the controller to control access. It's mostly in the view's that things got messy.
We did look at CanCan as we started getting different levels of user authorization. But I can tell you, this can balloon into rather gnarly code quickly unless you carefully segregate who can see and do what.
Devise provides you with the user_signed_in? method and the current_user method to help you with this kind of thing. For example, in your view you could have something along the lines of:
<% if user_signed_in? %>
<%= current_user.username %>
<% end %>
etc.
If your permissions get more complicated, I would recommend using an authorization gem to help you manage your restricted sections. A couple of examples are Declarative Authorzation (my personal favorite) and CanCan.

Rails 3: How Does One Restrict Access to IDs

This might be very simple; I don't know Rails very well.
I have a match myController/myAction/myID in my routes.rb that will direct hyperlinks to the proper page (using link_to). But here's the problem: I don't want people to be able to freely modify the id parameter, passing in via the URL whatever they like.
Is there a way to perhaps restrict access to routes to the link_to method only? Or maybe there's another way to go about this, using a passed in hidden variable param or something?
Users access you site via urls like: /controller/action/:id right? A user can change an id and must not view another non authorized resource. How to achieve this?, on your controller, return only those resources that user is allowed to access.
For example, suppose that you are using devise:
class AController < ApplicationController
def index
#resouces = current_user.find_all_by_id params[:id]
end
end
This way if the user tries to access something he does not have access to, he will get an error.
Hope this helps, if not please let me know and I'll try to elaborate.
About current_user, yes it is supposed to be the current logged in user, it doesn't have to be devise, you can implement your own session handling logic and then create a helper method to retrieve the currently logged in user.
About using devise, if you don't want to implement your own session handling logic, plus if you want features like:
remember me
already created views that you can fully customize
authentication
authorization
password encryption
many more (please look at the docs for further information)
Then devise is a good way to go.
Also, it is always a great idea, if possible and as a learning exercise, implement your own authentication and authorization layers, you won't regret.
Best regards
Emmanuel Delgado