How to have two different portals with devise? - ruby-on-rails

This is my routes.rb:
scope '/staff' do
authenticated :staff_member do
root to: 'staff/schedule_entries#index'
end
unauthenticated :staff_member do
root to: 'staff/chains#index'
end
scope '/:chain_id', constraints: StaffChainConstraint do
devise_for :staff_members, path: '', controllers: {
sessions: "staff/sessions",
passwords: "staff/passwords",
}, only: [:sessions, :passwords]
end
end
scope '/franchisee' do
authenticated :staff_members do
root to: 'franchisee/locations#edit'
end
unauthenticated :staff_members do
root to: 'franchisee/chains#index'
end
scope '/:chain_id', constraints: StaffChainConstraint do
devise_scope :staff_member do
get 'sign_in', to: 'franchisee/sessions#new', as: :new_franchisee_session
post 'sign_in', to: 'franchisee/sessions#create', as: :franchisee_session
end
end
end
The issue I'm running into is after signing from the page franchisee/:chain_id/sign_in, it keeps redirecting to staff/schedule_entries#index instead of franchisee/locations#edit. What am I missing to make this work?
Edit: Here's my franchisee/sessions controller:
# frozen_string_literal: true
module Franchisee
class SessionsController < Devise::SessionsController
helper_method :current_brand, :current_chain
before_action :configure_sign_in_params, only: [:create, :new]
protected
def respond_to_on_destroy
path = if current_admin
admin_root_path
else
after_sign_out_path_for(resource_name)
end
redirect_to path
end
def current_chain
#current_chain ||= Chain.find_by!(slug: params[:chain_id])
end
def current_brand
current_chain.brand
end
def configure_sign_in_params
devise_parameter_sanitizer.permit(:sign_in, keys: [:username, :password])
end
def set_raven_context
Raven.tags_context(app: 'franchisee')
Raven.user_context(
type: 'franchisee',
username: params.dig(:staff_member, :username),
brand_slug: current_brand&.slug,
chain_slug: params[:chain_id],
)
end
end
end
I made sure this controller is hit when submitting the sign in form from the page franchisee/:chain_id/sign_in. I also tried to fiddle around with after_sign_in_for but wasn't able to figure out a good way for it to tell between staff and franchisee.

Related

Rails merit-gem cannot score points on confirmations

I tried following the Wiki about the badge grant on confirmation but no luck. Is it supported for points as well? it doesn't explicitly mention in the Wiki.
[merit] no target found: uninitialized constant Users::Confirmation
Did you mean? Users::ConfirmationsController.
My devise routes:
devise_for :users, controllers: {
sessions: 'sessions',
omniauth_callbacks: 'users/omniauth_callbacks',
confirmations: 'users/confirmations',
passwords: 'passwords'
}
My confirmations controller:
module Users
class ConfirmationsController < Devise::ConfirmationsController
layout 'new_confirmation', only: %i[new create]
layout 'edit_confirmation', only: %i[edit update]
def show
super
#confirmation = resource # Needed for Merit / Must be AFTER the super
end
My Points rules:
module Merit
class PointRules
include Merit::PointRulesMethods
def initialize
score 1_000_000_000, on: 'users/confirmations#show', category: 'account_activity', &:confirmed?
end
end
end

【Rails】How can I write child directory path in route.rb?

The code is below.
#app/controllers/admin/feeds_controller.rb
class Admin::FeedsController < ApplicationController
def api_index
#routes.rb
Rails.application.routes.draw do
scope '/hoge' do
resource :feeds, only: [] do
collection do
get :api_index
end
end
end
end
My wish is that path is hoge/feeds/api_index and can execute api_index action in admin/feeds_controller.
The routes.rb is currently Routing Error.
Because the path is controller/feeds.
How can I call api_index action in controller/admin/feeds?
Thank you.
Error(Add)
I wrote the below
#routes.rb
Rails.application.routes.draw do
scope '/hoge' do
resource :feeds, controller: 'admin/feeds', only: [] do
collection do
get :api_index
end
end
end
end
Then, I got a error
undefined local variable or method `api_index' for Admin::FeedsController:Class
But I definitely wrote def api_index in app/controllers/admin/feeds_controller.rb
How Can I do that?
You can use namespace.
More info in the Rails guide: https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
#app/controllers/admin/feeds_controller.rb
class Admin::FeedsController < ApplicationController
def api_index
end
end
#routes.rb
Rails.application.routes.draw do
namespace :admin do
scope '/hoge' do
resource :feeds, only: [] do
collection do
get :api_index
end
end
end
end
end

You are being redirected. Rails 5 + Devise

My rails application successfully logs out a user and redirects to the about page when in development mode. But the moment i deploy it to production it returns a 302 status and a page that shows "you are being redirected". Am using devise for authentication below is what my code actually looks like.
The routes
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "users/registrations", confirmations: "users/confirmations", sessions: "devise/sessions" }, skip: [:sessions]
devise_scope :user do
get "login" => "devise/sessions#new", as: :new_user_session
post "login" => "devise/sessions#create", as: :user_session
get "/join" => "users/registrations#new", as: :join
get '/logout', to: "devise/sessions#destroy", as: :destroy_user_session
end
resources :companies
get "/about", to: "pages#about"
get "/faq", to: "pages#faq"
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'pages#home'
end
My application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
protected
def after_sign_in_path_for(resource)
company_path(resource)
end
def after_sign_out_path_for(resource_or_scope)
"/about"
end
def store_location
session[:return_to] == request.full_path
end
def clear_stored_location
session[:return_to] = nil
end
def redirect_back_or_to(alternate)
redirect_to(session[:return_to] || alternate)
clear_stored_location
end
end
And finally my link to log out.
<%= link_to "Log out", destroy_user_session_path %>
Please note that i am using devise 4.2.0 and capistrano for deployment.
Regards
~
I had to override devise sessions#controller and changed my routes to:
delete 'logout', to: "users/sessions#destroy", as: :destroy_user_session
Then i added delete method to my link for logging out.

Devise - creating users only by admin

I'm creating an app where I need only admins to create new users:
routes.rb:
devise_for :users, :skip => [:registrations]
resources :users
root 'dashboard#index'
users_controller.rb
# GET /users/1/edit
#def edit
#
#end
# POST /users
# POST /users.json
def create
build_resource(sign_up_params)
respond_to do |format|
if resource.save
format.html { redirect_to user_path(resource), notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: user }
else
clean_up_passwords resource
respond_with resource
end
end
end
When I open http://localhost:3000/users/new
I got this error:
AbstractController::ActionNotFound at /users/new
Could not find devise mapping for path "/users/new".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
What is wrong there? Thank you a lot!
The problem is that you're confusing Devise functionality with that of your app:
#config/routes.rb
resources :users #-> nothing to do with devise
When you create a user, you're using the devise build_resource helper. Problem being that this will require devise functionality, which is not going to happen for users_controller.
To use sign_up_params or build_resource, you'll have to scope your routes to a devise controller (so all the available session data is there)...
#config/routes.rb
devise_for :user, skip: [:registrations]
devise_scope :user do
resources :users, path: "", only: [:new, :create], controller: "registrations" #-> url.com/users/new
end
This way, you'll be able to override the standard Devise::RegistrationsController with your own code:
#app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :authenticate_user!
before_action :check_admin
def create
build_resource(sign_up_params)
...
end
private
def check_admin
redirect_to root_path unless current_user.admin?
end
end
--
What I would recommend is either removing the Devise functionality from your users controller, or overriding the registrations controller so that only an admin can create a user (which it seems you're trying to do already).

How to handle routes in rails api

I am learning api on rails,and my code is below
routes.rb
require 'api_constraints'
Rails.application.routes.draw do
devise_for :users
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :users, :only => [:show]
end
end
end
users_controllers.rb
class Api::V1::UsersController < ApplicationController
respond_to :json
def show
respond_with User.find(params[:id])
end
end
when I run the rails server with localhost:3000/users/1 then It gives me the error No route matches
Then i checked routes using rake routes and it is included in my routes
`api_user GET /users/:id(.:format) api/v1/users#show'
but i don't know why it gives me the error
api_constraints.rb
class ApiConstraints
def initialize(options)
#version = options[:version]
#default = options[:default]
end
def matches?(req)
#default || req.headers['Accept'].include?("application/vnd.marketplace.v#{#version}")
end
end
`
Try the following:
api.lvh.me:3000/api/v1/users/1
You've setup a constraint that requires an api sub domain. You'll need to remove the constraint to make the following work:
lvh.me:3000/api/v1/users/1
Note: lvh.me points to 127.0.0.1

Resources