I was wondering if anyone knows a simple way to make devise 'create' an account if it doesnt exist at login, allowing me to use a single page.
Yes, this is possible. Devise's sessions#create method yields to a block - see https://github.com/plataformatec/devise/blob/master/app%2Fcontrollers%2Fdevise%2Fsessions_controller.rb#L20
So, you'd need to override that controller's create method, and use the yield to add a new account if the user is not successfully signed in.
Edit: here's a quick pseudo-code example of what your overriden create method should look like:
def create
super do |user|
return if current_user # successful login
# Here, if the user doesn't exist,
# create a new record and log them in.
end
end
You need to custom your controller and put the 'create' action in it.
Here's the guide for customizing your controller: https://github.com/plataformatec/devise#configuring-controllers
Related
Is it possible to access controller parameters when defining abilities in ability.rb?
I have an event and users that can participate in or create that event. It seems like I could create a different controller action for every possible scenario, e.g. a user signs himself up for an event or a creator deletes someone from the event. However I think it would be a lot easier to read to have less actions and be able to define abilities based on what parameters are being passed in from the client.
Answer
#chumakoff has some good info down below that helped explain how CanCanCan is working. I decided to authorize these actions by default in ability.rb, and then raise an error, e.g. raise CanCan::AccessDenied.new("You cannot delete someone else from this event"), in the controller if I detect incorrect user/event parameter IDs being sent in.
If I understand correctly, you are using cancan's authorize_resource or load_and_authorize_resource controller helper that calculates user abilities based on controller actions names.
But it's not obligatory to use this helper for all actions. You can skip it for actions having complex ability logic and check abilities manually.
For example:
class ParticipationsController < ApplicationController
authorize_resource except: :create # skiping `authorize_resource` for `create` action
# ...
def create
if creator_adds_someone_to_event?
authorize! :add_to, #event
end
if user_signs_up_for_event?
authorize! :sign_up_for, #event
end
# ...
end
So, you can check many different abilities in the same controller action. Just disable default cancancan's behaviour for the action.
Yes there is a debugging tool Named as " pry" . Use that it would help u out. Just use binding.pry wherever u want to check the value of parameters in the code and the console will stop executing at that moment so u can check the value of the parameters.
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")
How do I execute a particular function after a user has signed up.
(I wanted to add to one of my associations, I already have it coded in a non-devise rails but now I need it here)
Device has provided helper action 'after_sign_in_path_for' you can override it within your application controller.
def after_sign_in_path_for(resource_or_scope)
.... #write your customize code or call any method
end
For sign up it would look like:
def after_sign_up_path_for(resource_or_scope)
if resource_or_scope.is_a? User # and perhaps other conditions
#... do something, go somewhere
else
super
end
end
Ofc. Assuming that your Devise user model is called User.
You can use the after_create callback in your User model.
The following guide has tons of examples: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
I am using Devise, and when someone logs in I would like to execute a custom method.
Similarly to how you use before_save to execute a method before the account/model is updated/saved, or before_create to do the same before the object is initially created.
I would like to do the same, but for users logging in.
How do I do that ?
In your application_controller.rb add the following code:
def after_sign_in_path_for(resource)
execute_custom_function()
super
end
You can utilize Devise's Controller Helper.
I have a function to take ownership of a job which updates the database to update the username in a table row. I want to link to this function from the view and then redirect to the appropriate page.
How do you link to a controller function or a model function from the view?
from the index i want to have another link beside show, edit, delete, which says 'take ownership'
This will then fire off an action in the application controller
def accept_job(job_type, id, username)
if (job_type == 'decom')
Decommission.update(id, :username => username)
else
end
end
You can use the instance variable #controller to get a reference to the controller. As for calling a model function, you can call Model.function to call class methods, or if you have a particular Model instance called model_instance, then use model_instance.function to call an instance method.
Edit: Okay, I think I understand what you're asking now.
You should
Create a new action in the controller, let's call it update_username:
def update_username
job = Job.find(params[:id])
job.your_method #call your method on the model to update the username
redirect_to :back #or whatever you'd like it to redirect to
end
Add your action the routes in routes.rb. See Rails Routing from the Outside In for more details.
Add your link in the view:
<%=link_to "Update my username please!", update_username_job_path%>
First you create a function in your model, say
class Decommission
def assign_permission(name)
#your update code
end
end
As I can see, you can do this in 3 different ways
1 - Create a helper method to update the permission (This can be done either in Application helper or helper related to your view)
2 - By creating a controller method (as you proposed) But if you are not using this method in other views you dont need to create this method in application controller
3 - If you want to use your method in both controllers and views, create your method in application controller and make it as helper method. By that way you can access it from controllers as well as views
cheers
sameera