reset_password_instructions.html.erb uses what layout - ruby-on-rails

I'm using Rails and Devise for user management.
I'd like all my emails to be consistent in style and modify of Devise password reset email.
reset_password_instructions.html.erb features only contents of the . There has to be a layout it uses somewhere, but I cannot find it...

You can define a layout for all Devise mail using an initializer.
config/initializer/devise.rb
Devise.setup do |config|
# Other options here...
config.to_prepare do
Devise::Mailer.layout "email" # email.haml or email.erb
end
end
https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts
You would have to create a new email layout with the name you identified in Devise::Mailer.layout but that's a good thing since now you have complete control over the code.

Related

Setting up automatic password with Devise

I have setup Devise, I have set up the below code in my user.rb file
def self.create_auto_password
generated_password = Devise.friendly_token.first(8)
self.create(password: generated_password, password_confirmation: generated_password)
end
How can I get into the Devise registration controller to then call my new method which I have set up to auto generate a password?
You can access the devise controllers after installing Devise by running the following on your command line:
rails generate devise:controllers
This will generate a 'Devise' folder in your controllers folder. You can then modify the controllers as needed. It sounds like you would like to modify the registration controller to add the auto-setting password.
You can find more docs on their .git page here: https://github.com/plataformatec/devise

How to protect rspec_api_documentation apitome route without a controller

I have a set of API documentation pages that I want to password protect using devise. The docs are generated using rspec_api_documentation. The gem uses rspec to execute the API methods and create html or json doc files. I'm generating json and using another gem, apitome, as a viewer.
This is all working beautifully and my api docs can be found at /api/docs, but I can't figure out how to require authentication to view the docs.
The docs are viewed through apitome so it using rails. There isn't a route in routes.rb, but the apitom initializer mounts the docs.
From apitom initializer:
# This determines where the Apitome routes will be mounted. Changing this to "/api/documentation" for instance would
# allow you to browse to http://localhost:3000/api/documentation to see your api documentation. Set to nil and mount
# it yourself if you need to.
config.mount_at = "/api/docs"
https://github.com/zipmark/rspec_api_documentation
https://github.com/modeset/apitome
I found this How-to that is supposed to make every page on the site require authenication, but I'm still able to hit the docs url without signing in.
#https://github.com/plataformatec/devise/wiki/How-To:-Require-authentication-for-all-pages
Thanks for any help.
You can take control of Apitome controller and request auhentication.
configure apitome to not mount itself by setting mount_at to nil
write your controller ApidocsController extending Apitome::DocsController
add before_filter :authenticate_user! in your controller
add a route to your controller: get '/api/docs', to: 'apidocs#index'
Controller implementatin would go like this:
class ApidocsController < Apitome::DocsController
before_filter :authenticate_user!
end
If you have Devise already configured (for example if you already use ActiveAdmin) you can share the same authenticated session.
You have to disable the default mounting of Apitome:
# config/initializers/apitome.rb
Apitome.setup do |config|
config.mount_at = nil
# ...
end
Since this will break links in Apitome, you have to add to your application.rb:
# config/application.rb
# ...
class Application < Rails::Application
config.after_initialize do
Apitome.configuration.mount_at = '/docs'
end
# ...
end
Then force mount of the Apitome engine under Devise authenticated session:
# config/routes.rb
Rails.application.routes.draw do
# ...
authenticated :admin_user do
mount Apitome::Engine => '/docs'
end
# root_to ...
end
Now /docs is accessible only for already authenticated users.
PS: replace :admin_user (default for Active Admin) to :user or any other model name where Devise is configured.
I am using the cut down rails api, so did not have any views or devise and so no simple way to implement password protection. Accordingly I went for the following solution.
Apitome.setup do |config|
config.mount_at = nil
# ...
end
and in the routes.rb file:
mount Apitome::Engine => '/api/docs' unless Rails.env.production?
Finally, I just did a pdf of the api/docs page, and then sent the pdf to anyone what had a right to see the documentation. Obviously not suitable for a large user base, but works fine for a small one, e.g. within a company's IT group.
If anyone is using Raddocs, add mounted route inside authentication block as below:
authenticate :user do
mount Raddocs::App => "/docs"
end

How to change "Devise: password reset instruction email's subject"

I'm just unable to change "password reset instruction" email's subject. I have changed notifer.rb in Mailer to overwrite Devise default email subject. But it's not working.
Here in my application there is default Email subject inside Devise .yml file. But I want to make it dynamic to change it by pulling data from DB.
you can change it in devise.en.yml file in intilizer directory
And set your own subject for any mailer
mailer:
confirmation_instructions:
subject: 'Confirmation instructions'
reset_password_instructions:
subject: 'Reset password instructions'
unlock_instructions:
subject: 'Unlock Instructions'
I got this to work by creating my own sub-class of Devise::Mailer.
class DeviseMailer < Devise::Mailer
def reset_password_instructions(record, token, opts={})
mail = super
# your custom logic
mail.subject = "[SOME DB DATA]"
mail
end
end
And then modifying the devise.rb initializer to use my mailer.
# Configure the class responsible to send e-mails.
config.mailer = 'DeviseMailer'
Change option :subject:
class DeviseMailer < Devise::Mailer
def reset_password_instructions(record, token, opts={})
opts[:subject] = 'SOME DB DATA'
super
end
end
You can write your own method inside your controller and call the respective mailer template. This will help you.. Else devise views, there will be a view page to send reset instruction. Change the content there..
For default foreign language (example Japanese)
STEP 1 Create a 'ja.yml' in config/locales/ (or whatever filename)
ja:
devise:
mailer:
confirmation_instructions:
subject: '仮会員登録完了のお知らせ'
reset_password_instructions:
subject: 'パスワード再設定手順のお知らせ'
STEP 2 On config/environments/development.rb
config.i18n.default_locale = :ja
STEP 3 Restart server
If you're willing to translate your Devise messages, which was my case, a better practice would be creating a new yml file in config/locale and changing your application's locale at config/application.rb
To illustrate, I had to create devise.pt-BR.yml inside config/locale.
Then I copied its translations from internet, on this link.
Finally, I set my application's new locale at config/application.rb as follows:
config.i18n.default_locale = :'pt-BR'
Hope it helps some of you guys having the same problem as mine.

Custom variables in Devise reset password instructions?

I need to be able to customise the rails devise mailer view for reset password instructions.
for this I need to do two things.
Specify a custom URL for the link, so that its a host/domain based on a certain business logic. This host and domain comes from the URL in the browser, i.e. the request object, when the user clicks forgot password. So I do not have the request object in delayed_job to process it as I need, hence I need to be able to do this at some point in the delayed_job that is sending the email.
Pass custom variables to the mailer view, so that I can add in various other logic for the view, hiding and showing bits as I need.
Can anyone help? I can see that you can generate the mailer views for devise, but I need to be able pass over various items to it also. Do I need to somehow override the functions myself in my User model and password controller for example?
Overriding the whole controller method and adding param in send_reset_password_instructions opts parameters will fix it.
#resource.send_reset_password_instructions(
email: #email,
provider: 'email',
redirect_url: #redirect_url,
client_config: params[:config_name],
parameter_passed: params[:parameter_passed],
)
You can access the param in the view as message['parameter_passed']
I struggled with this too before I realized that declaring custom variables BEFORE calling super will work.
def reset_password_instructions(record, token, opts={})
#custom_variable = "Greetings, world"
# your gorgeous code
mailer_object = super
mailer_object
end
so, after much ado and searching and hacking around with stuff... this is just not possible. so I ended up writing my own mailer and bypassing the devise reset password methods in the controllers, to generate my own reset token, set my variables I needed, called my usermailer.... and embedded the devise url in my mail to get it back calling devise once the password reset link was clicked, and all was fine then....
I hated having to rewrite the logic, but in the end its the quickest and cleanest solution.
One approach that nearly worked, was using a non activerecord attribute on my user model to store the bits I needed and "hacking" that into the #resource in the devise view, but it was causing some grief in devise doing so, as a result, I went with the option above...
I needed to add a source to be included into the reset password view, here's what I implemented:
class User < ActiveRecord::Base
prepend ResetPasswordWithSource
devise :recoverable
....
end
module User::ResetPasswordWithSource
def send_reset_password_instructions(source=nil)
#source = source
super()
end
def send_devise_notification(notification, *args)
args.last.merge!({ source: #source })
super
end
end
From here you can just call user.send_reset_password_instructions('special_source')
And can access in views via #options[:source] = 'special_source'
You just need to add a flag to display in the view mailer. From here you can just call a method and pass the parameter.
#user.send_reset_password_instructions("true")
Now override the method send_reset_password_instructions
def send_reset_password_instructions(option = nil)
token = set_reset_password_token
send_reset_password_instructions_notification(token, option)
token
end
def send_reset_password_instructions_notification(token, option = nil)
send_devise_notification(:reset_password_instructions, token, :option => option)
end
Then you can access the parameter by using:
message[:option]

Where should warden callbacks be placed in a rails app?

I'm relatively new to rails. I have Devise set up, and want to run some callback code after users sign in.
Looking at the Warden wiki page, I can use the "after_set_user" callback to perform this logic, for example:
Warden::Manager.after_set_user do |user, auth, opts|
unless user.active?
auth.logout
throw(:warden, :message => "User not active")
end
end
However, I'm not sure where I should be storing this stuff. My first thought is that I could put it in config/initializers/devise.rb. Is that correct? It doesn't feel right putting what is essentially controller code in the config directory.
Warden hooks need to be required when your application is booting, so inside Devise's initializer at config/initializers/devise.rb is a good candidate.
However, the behavior you want to achieve will be better accomplished by using this Devise feature:
https://github.com/plataformatec/devise/wiki/How-To:-Customize-user-account-status-validation-when-logging-in

Resources