Rails 4 - set session variable so user can see pages only during that session - session

I am using rails 4 and want to give an instant quote that has some personal information. I need to make the quote viewable for someone's entire session WITHOUT having them log in but someone else session could not see that quote. The idea is that they can see the quote I give them and download that quote as a PDF. Here is the essence of what I have in my controller - but it is not working.
class ClientsController < ApplicationController
before_filter :check_guest, :only => :show
def check_guest
# # if user isn't logged in
if current_user.nil?
# # if user has already viewed, redirect
# if session[:viewed] == true
# flash[:alert] = "You can only view a quote once. Please resubmit your information."
# redirect_to root_path
# # if user hasn't viewed, allow access, but flag as having viewed
# else
# session[:viewed] = true
# end
if session[:quote_id] == params[:id] # where params[:id] is the quote ID
flash[:alert] = "Allow"
else
flash[:alert] = "Dont Allow"
end
end
end
I imagine I need to set variable session[:quote_id] = #client.id but am not sure if I do that in the create action or the show action. Either place I put it, the entire code is not working. Any help is greatly appreciated. Thank you.

Two things I needed to do.
First, set the session variable as the LAST action in create.
def create
....some actions
session[:quote_id] = #client.id
end
Next, I had to convert the params ID into an integer, so it would evaluate correctly.
session[:quote_id] == (params[:id].to_i)

Related

Ruby - devise : confirmations_controller stop registrations_controller

I have a problem with devise I can't find the solution.
When a user sign_up, I need to call several services to make his profile. So here is the registrations_controller.rb.
require_relative '../../../app/services/affinities'
require_relative '../../../app/services/astroprofil'
require_relative '../../../app/services/geocode'
class Users::RegistrationsController < Devise::RegistrationsController
ASTROPROFIL = Astroprofil.new
AFFINITIES = Affinities.new
GEOCODE = Geocode.new
after_action :create_astroprofil, only: %i[new create]
after_action :create_affinities, only: %i[new create]
private
def create_astroprofil
return unless user_signed_in?
ASTROPROFIL.profil(current_user)
end
def create_affinities
return unless user_signed_in?
affinities(current_user, ten_mates)
end
def affinities(user, mates)
AFFINITIES.partner_report(user, mates)
AFFINITIES.sign_report(user, mates)
AFFINITIES.match_percentage(user, mates)
end
def ten_mates
mates_by_gender = User.where(gender: current_user.looking_for).where.not(id: current_user.id)
return mates_by_gender.sample(10)
end
end
When I sign up everything works perfectly, a new user is entirely created.
But as soon as I try to add a confirmation per mail with devise, the mails are sent but it stops the 'create_astroprofil' and the 'create_affinities' methods.
Do you have any idea about what's happening ?
I would say it's coming from this line
registrations_controller.rb#L28
Since you cannot login without having confirmed your email, I'm pretty sure create_astroprofil and create_affinities are called but their first line is return unless user_signed_in?.
2 options here:
Astroprofil.new and Affinities.new can be called for an unconfirmed user
Called create_astroprofil and create_affinities from ConfirmationController#show

Record Not Found rails 5 ActiveRecord Error

I am trying to use a vanity URL that uses the SecureRandom issued ident to a culvert, and then display that culvert via the show page.
This is a screenshot of the error message:
This is a screenshot of the browser url:
My Culvert Controller is:
I have tried Both:
#culvert = Culvert.find_by_culvert_ident(params[:id])
AND
#culvert = Culvert.find_by_id(params[:culvert_ident])
In my culvert controller show action, both yield the same result (screenshot)
private
# Use callbacks to share common setup or constraints between actions.
def set_culvert
#culvert = Culvert.find_by_culvert_ident(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def culvert_params
params.require(:culvert).permit(:culvert_ident, :latitude, :longitude, :address, :user_id)
end
This is my Culvert Model ident generator and vanity url methods:
before_create :generate_culvert_ident
# Relationships
belongs_to :user
# Model Validations
validates_uniqueness_of :culvert_ident
# Ident Generator
def generate_culvert_ident
begin
self.culvert_ident = SecureRandom.hex(3).upcase
other_culvert = Culvert.find_by(culvert_ident: self.culvert_ident)
end while other_culvert
end
# Url Direction
def to_param
culvert_ident
end
So my goal is to create the culvert, auto assign a unique identifier, save it and display the culvert using the custom identifier as opposed to the standard 1,2,3,4 id's
this works in another web app i have used, is setup exactly the same but i am getting this error here and cant figure out why. Please let me knwo if you require further info!
**
EDIT # 1 - Adds Screenshot of Console output
**
So the issue here was that I removed the culverts controller
before_action :set_culvert
as soon as I re-added the set_user action the issue was resolved.
thanks for your assistance!

Blocking Users From Specific Pages using Ruby on Rails and cancan

I am learning Ruby on Rails and was looking into utilizing cancan to help restrict users access to actions that they shouldn't have and to pages depending on who they are. I currently understand how to restrict actions, but I was curious if someone could help with actually restricting certain pages and unique pages.
One example is I have a home page for admin users and one for regular users, how would I restrict the admin page from the normal user?
Thanks, and any pointers on if I am doing something wrong is greatly appreciated.
If you want to use cancan :
Admit you add in your user controller a method admin_home :
def admin_home
#user = current_user
authorize! :admin_home
end
You need to specify in ability.rb file you want to restrict access to admin_home for standard users :
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
#Authorize all actions
can :manage, User
else
#authorize only self modifications and restrict access to admin_home
can :manage, User, :id => user.id
cannot :admin_home, User
end
end
end
You can find great resources about cancan in official wiki like
https://github.com/ryanb/cancan/wiki/Defining-Abilities and
https://github.com/ryanb/cancan/wiki/Authorizing-controller-actions
Hope this help
Note: I am just giving you an example, you are not supposed to use it as it is, but you can have an Idea that how you will be able to put your logic.
class AdminsController < ApplicationController
before_filter :check_admin, :only => [:index, :show]
def index
#admins = //whatever your query for this action
end
def show
#admin = //whatever your query for this action
end
protected
def check_admin
if(my_condition to check if user type is admin)
{
return true // or anything u want for ur admin user
}
else
{
//anything here when user is not admin
1. you can redirect to users home page using redirect_to
2. you can redirect to a specific page which shows "You are not authorized to see this web page"
}
end
end
end

Showing users unique info when facebook authenticate , with Sinatra/ Ruby

Super beginner here.
Here's what I am trying to do:
Build a basic to do list app, where User X logs in with facebook, adds some items, sees them, logs out. User Y/Z/M/etc, should be able to log in see their OWN list, add their OWN items, etc.
AKA: a standard web app where you log in to your account and see your own info.
What I have so far:
Ability to build a list, log in with Facebook and having it know your name.
However, the list stays the same whether I log in or whether my friend logs in with her account.
What I need to do, and don't know how:
I need each user to be able to create and see their own list, and be able to come back to it and still see it/ add to it, etc.
I don't even know how this is called, would this be a database of users each with their own set of data? Would the lists need to be set up so they could be stored as a chunk of data?
Does it have something to do with this :Sessions in Sinatra using Facebook authentication If so, what?
If anyone could be give me some really really basic directions as to where to go from here, any tutorials or what I should be googling for, that'd be awesome.
Here's my main piece of code (warning: it's really messy) :
require 'sinatra'
require 'data_mapper'
require 'time'
require 'rubygems'
require 'json'
require 'omniauth'
require 'omniauth-facebook'
#TODO require 'omniauth-att'
SCOPE = 'email,read_stream'
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/queue.db")
class SinatraApp < Sinatra::Base
configure do
set :sessions, true
set :inline_templates, true
set :protection, :except => :frame_options
end
class Note
include DataMapper::Resource
property :id, Serial
property :content, Text, :required => true
property :complete, Boolean, :required => true, :default => false
property :created_at, DateTime
property :updated_at, DateTime
end
class User
include DataMapper::Resource
property :id, Serial
property :uid, String
property :name, String
property :created_at, DateTime
end
###### no clue what this does ##############
DataMapper.finalize
DataMapper.auto_upgrade!
enable :session
use OmniAuth::Builder do
provider :facebook, '464630283595639','5e4c7ad43bf111c10287c981d51127a3',:scope => SCOPE, :display => "popup"
#provider :att, 'client_id', 'client_secret', :callback_url => (ENV['BASE_DOMAIN']
end
###### root ##############
get '/' do
if current_user
#notes = Note.all :order => :id.desc
#title = 'Movie Queue'
erb :home
else
' sign in with Facebook'
end
end
###### authentication ##############
["/sign_in/?", "/signup/?"].each do |path|
get path do
redirect '/auth/facebook'
end
end
get '/auth/:name/callback' do
auth = request.env["omniauth.auth"]
user = User.first_or_create({ :uid => auth["uid"]}, {
:uid => auth["uid"],
:name => auth["first_name"],
:created_at => Time.now })
session[:user_id] = user.id
redirect '/'
end
helpers do
def current_user
#current_user ||= User.get(session[:user_id]) if session[:user_id]
end
end
##list making part###
post '/' do
n = Note.new
n.content = params[:content]
n.save
redirect '/'
end
get '/:id/delete' do
n = Note.get params[:id]
if n.destroy
redirect '/', :notice => 'Note deleted successfully.'
else
redirect '/', :error => 'Error deleting note.'
end
end
get '/:id/complete' do
n = Note.get params[:id]
n.complete = n.complete ? 0 : 1 # flip it
n.save
redirect '/'
end
########## logout and error handlers #############
get '/logout' do
session[:user_id] = nil
redirect '/'
end
get '/auth/failure' do
erb "<h1>Authentication Failed:</h1><h3>message:<h3> <pre>#{params}</pre>"
end
get '/auth/:provider/deauthorized' do
erb "#{params[:provider]} has deauthorized this app."
end
get '/protected' do
throw(:halt, [401, "Not authorized\n"]) unless session[:authenticated]
erb "<pre>#{request.env['omniauth.auth'].to_json}</pre><hr>
<a href='/logout'>Logout</a>"
end
end
########## don't know what this is #############
SinatraApp.run! if __FILE__ == $0
Disclaimer: I don't know Datamapper, but this should get you going.
There needs to be a way to associate a note with a user. This needs a table in the database, some would call it users_notes, personally I prefer users_rel_notes, (perhaps Datamapper has a convention for this… YMMV). Anyway, the table will have a minimum of 2 columns - the user's id, and the note id. You don't need a separate table as I wrote before (I'm lacking a bit of sleep, sorry!), that would be for a many to many relationship where a user could have several notes and a note could be associated with several users. For what you have, where only the owner of a note has access to it, it requires a one to many relationship. You could add a column to the notes table to store the user id.
Then, in the User class, add an association to the Note class, it's a one to many association and in Datamapper that's a has n, e.g.
has n, :notes
Now when you have a user instance, you can (probably) call the notes for that user via:
user.notes
I see you have the helper current_user defined, so if someone is logged on you could call current_user.notes to get back all the notes for the logged in user.
Remember, when you add a note to make sure you add a record to the association table, (probably, read the link) via user.notes << my_new_note.
The session is the information you keep around to identify the user and any other little bits of info that you may recurrently need. The likelyhood is, you're just storing an id for the user, or the facebook token that identifies them, and then during a request, if it's needed then you'll look inside the cookie, grab the id, look up that user by the id and get a user instance. Session info can be stored in several ways, most often cookies but you can use anything you would use to store any other data.

Session values aren't kept

I'm using a JRuby(latest, 1.7 RC2)/Sinatra mix on the Trinidad server, for background info.
get "/" do
#user = session[:user] || [3,2]
puts session[:user]
haml :home
end
get "/signed_in" do
"#{session[:loggedin]}"
end
post "/signup" do
user = User.create(:username => params[:username], :password => Digest::SHA1.hexdigest(params[:password]))
session[:user] = user
session[:loggedin] = true
puts session[:user]
end'
What I expect as output is (with comments):
# blank line
#<User:0x4049839a>
#<User:0x4049839a>
But what I really get is:
# blank line
#<User:0x4049839a>
# blank line
And after the post, /signed_in will still have no value to output, when it really should be true.
Why aren't these values being kept? No, I'm not using shotgun, I do have sessions enabled, and I do have a session secret set up.
You cannot keep DataMapper resources in session variables. Instead put the key to your user object in your session variable and use a before helper to set #user = User.first(session[:user]) and use the #user instance variable throughout your application
Also, you do not need the session[:loggedin] entry, just use #user.nil?

Resources