Allow users to edit account, without id being in url - ruby-on-rails

I know that in devise if you want to edit your account you can go to /registrations/edit to edit the account.
However I'm on a project where I'm just using omniauth. So I created a controller called
users_controller
that will allow the user to edit their account information etc. However if I do
edit_user_path
it want's me to give the id, how can I do this but still have a clean URL like devise does, where I don't have to make it users/:id/edit?

In devise, you don't need the id because the id is calculated by the current_user which is stored in session.
So, if you want to edit your user's profile without an id, you must ensure the id could be found somewhere, via session/cookie.
# set into session
session[:user_id] = 3
# read from session
User.find session[:user_id]
refer to: http://guides.rubyonrails.org/action_controller_overview.html#session

Related

Rails: Migrating to Auth0 while retaining postgres records and associations

My project currently uses has_secure_password to handle users (similar to this railscast). Everything works fine but looking down the road, I feel that a switch to Auth0 will provide benefits and would like to make the transition now before too many users sign up.
Users are saved to a User model with several associations (checkins/comments/etc.) How can I link an Auth0 user to a User record on my database. I figured I could either lookup by email (since they will be unique) or Auth0 User Id (and add a new column to the user table) once they login. It seems like I could simply use the Auth0 login callback to sign the user in (using my current sessions controller) but how can I create users on my database when they are created in OmniAuth. Is there a callback for that as well?
In a perfect world I would like to do something like:
User signs up using Auth0 lock. Creating a new account on the Auth0 database.
Callback triggers a new record to be made on my database that contains all the information from Auth0 and has columns for associations.
User logs in and their user_id (from my database) is stored in sessions.
Changes the user makes to personal information (name/email/etc.) is changed on both databases.
Is what I want possible? Or should I stick with my current authentication?
There is no major difference between implementing Auth0 authorization and any other OAuth provider such as Facebook, Twitter, Github etc. The Auth0 quickstart guide is just kind of strange since it does not show how you would link credentials to a user model in the application. Rather they just shove the whole shebang into the session.
The only real change you need to do to your user model here is add a uid column which is used to store the Auth0 uid for the user.
Basically the OAuth flow with OmniAuth works like this:
The user clicks a link that redirects the user to the providers OAuth portal. (Or in the case of Auth0 its a fancy JS Widget)
The provider redirects back to your application and it goes to either the callback or failure method on your callbacks controller.
At this point the user may be a new or returning user. So you try to find the user in your application based on the uid from the auth hash or create a new user from the auth hash.
You sign in and redirect the user.
class Auth0Controller < ActionController::Base
# the signed up or logged in on auth0
# GET "/auth/auth0/callback"
def callback
auth_hash = request.env['omniauth.auth']
#user = User.find_or_intialize_by(uid: auth_hash[:uid])
if #user.new_record?
#user.name = auth_hash.name
#user.email = auth_hash.email # etc
#user.save!
end
reset_session
session[:user_id] = #user.id
redirect_to root_path, success: "Hello #{#user.name}"
end
# the user declined to give your app permissions
# GET "/auth/failure"
def failure
redirect_to root_path, alert: "Oh noes"
end
end
See:
https://auth0.com/docs/quickstart/webapp/rails
https://github.com/omniauth/omniauth
https://auth0.com/docs/connections/database/migrating

How to allow sign in with devise if user is already authenticated?

There's an App which creates a new user when you first time open the site (if you don't have a cookie). Also you can sign in as different user. The problem is Devise doesn't allow to sign in as already authenticated user. Even if I override require_no_authentication in SessionsController warden still remembers the user through session.
I do aware about guest user pattern but there's no guest user. The app is intended to create real user accounts and allow to sign in as another users.
So the question is should I create new Warden strategy and if so, what checks shall I do there? Or there's another way?
Just reset the session in the desired action. You can just make the first line be reset_session, or make it a before filter, like so:
before_filter :deauthorize_user, only: [ :some_action ]
def deauthorize_user
reset_session
end

Devise allow access to protected url with link

I am developing an application which requires users to be logged in - but also want to allow them to share particular information with others - provided they have the correct link.
I am using devise, and check that the current_user has 'purchased' the object they are viewing.
It has come up in conversations that they would like this to be emailed to another person to view this information - but would not like them to have access to their account.
Ie.
unless current_user
redirect_to "/" and return
end
I imagine it will be a simple auth token in the url that I can check and allow them access if it is correct?
unless current_user or invalid_auth
redirect_to "/" and return
end
What is the best way to generate and store this auth token and what is the best implementation method
Cheers

Email based interaction with rails app

I need some gem that will allow users to interact with rails app through email, without need to register. For example: I publish something for sale, accompanied with email, and all of controls (CRUD, and submitting) I get on my email as links (delete, update, and so on). I'll like to, somehow connect it to devise, with opportunity of further registration using the same email with shopping history.
To publish something(services or products) for sale User has to fill:
name, email (validates unique), phone. That may or may not be used for future registration using devise.
in the same form may be: pictures, description, and other fields of product.........
the idea is to store: id, name, email, phone in user db without password, or be somehow pending for registration
Just create your own CRUD controller with authorization based on some hash that you will add to the URL. Store those hashes in the database and verify if user is legitimate to perform action.
Warning: anyone with the valid URL will be able to perform these actions.
Well, in comment you wrote that you want it to integrate with Devise. Devise supports login tokens but for existing users. You should then somehow virtually register them. Easiest approach would be to:
Include user email in the URL with some tolen
Check if we already have such user - add token verification here
user = User.find_by_email(params[:email])
if user.nil?
user = User.create(field_1: value1, field_2: value2)
end
sign_in(user)
redirect_to after_sign_in_path(user)
Done. User is authenticated based on the email and token included in the URL.

Rails: sign out logged in user on event

I'm using Rail3 with Devise gem. It does a great job when you need to lock user from signing in.
But it works just for new login attempts.
If he is already logged in - it won't sign him out immediately.
Here's is the typical use case:
Given admin user
when detects suspicious activity of certain user he locks it with malicious_user.lock('locking-reason')
% can config/initializers/session_store.rb
AppFoo::Application.config.session_store :cookie_store, :key => '_foo_session'
Given HTTP's statelessness, you can't immediately log out a user because you will need to wait until they make another request to your server. You could get around this via a push service I suppose, but that would be overkill.
My solution would be to add that person to a blacklist and then check if they're on the blacklist whenever they try to access a section intended for logged-on users only. This will render them unable to log on until you decide whether or not their activity is suspicious.
Example:
User is suspected of intolerable activity
Admin wants to check this out, so they temporarily add the user to the blacklist.
User clicks on an area of the page they were currently on when added to the blacklist.
Code checks for loggin status and blacklisted users.
Since the user is blacklisted, they are informed that they need to sign in to access the content
Once the user tries to sign in again you can inform them that their account has been temporarily disabled (or you can do this in the previous step).
perhaps the easiest way would be to redirect the user to the logout action when you lock them so:
malicious_user.lock('locking-reason')
redirect_to '/logout' and return
I'm not familiar with Devise so this may not be the best solution or even possible but it's how I would approach the problem
Use a before_filter in the ApplicationController that will do the following
before_filter :kick_out_blocked_user
protected
def kick_out_blocked_user
unless current_user.try(:active?)
redirect_to destroy_user_session_path
end
end

Resources