Module: PandaPal::Helpers::SessionReplacement

Extended by:
ActiveSupport::Concern
Included in:
ControllerHelper
Defined in:
lib/panda_pal/helpers/session_replacement.rb

Instance Method Summary collapse

Instance Method Details

#current_panda_sessionObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/panda_pal/helpers/session_replacement.rb', line 41

def current_panda_session
  return @current_session if defined?(@current_session)

  if params[:session_token]
    payload = JSON.parse(session_cryptor.decrypt_and_verify(params[:session_token])).with_indifferent_access
    matched_session = PandaPal::Session.find_by(session_key: payload[:session_key])
    if matched_session.present?
      if payload[:token_type] == 'nonce' && matched_session.data[:link_nonce] == payload[:nonce]
        @current_session = matched_session
        @current_session.data[:link_nonce] = nil
      elsif payload[:token_type] == 'fixed_ip' && matched_session.data[:remote_ip] == request.remote_ip &&
        DateTime.parse(matched_session.data[:last_ip_token_requested]) > session_expiration_period_minutes.minutes.ago
        @current_session = matched_session
      elsif payload[:token_type] == 'expiring' && DateTime.parse(matched_session.data[:last_token_requested]) > session_expiration_period_minutes.minutes.ago
        @current_session = matched_session
      end
    end
    raise SessionNonceMismatch, "Session Not Found" unless @current_session.present?
  elsif (session_key = params[:session_key] || session_key_header || flash[:session_key] || session[:session_key]).present?
    @current_session = PandaPal::Session.find_by(session_key: session_key)
  end

  @current_session
end

#current_session(create_missing: false) ⇒ Object

Deprecated.
  • User current_panda_session instead



67
68
69
70
71
72
73
74
75
76
# File 'lib/panda_pal/helpers/session_replacement.rb', line 67

def current_session(create_missing: false)
  current_panda_session

  if !@current_session && create_missing
    Rails.logger.warn("current_session(create_missing: true) is deprecated. Use start_panda_session! instead.") unless Rails.env.production?
    start_panda_session!
  end

  @current_session
end

#current_session_dataObject

Deprecated.


79
80
81
# File 'lib/panda_pal/helpers/session_replacement.rb', line 79

def current_session_data
  current_session.data
end

#forbid_access_if_lacking_sessionObject



87
88
89
# File 'lib/panda_pal/helpers/session_replacement.rb', line 87

def forbid_access_if_lacking_session
  render plain: 'You should do an LTI Tool Launch.', status: :unauthorized unless valid_session?
end


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/panda_pal/helpers/session_replacement.rb', line 120

def link_nonce(type: link_nonce_type)
  type = instance_exec(&type) if type.is_a?(Proc)
  type = type.to_s

  @cached_link_nonces ||= {}
  @cached_link_nonces[type] ||= begin
    payload = {
      token_type: type,
      session_key: current_session.session_key,
      organization_id: current_organization.id,
    }

    if type == 'nonce'
      current_session[:link_nonce] = SecureRandom.hex
      payload.merge!(nonce: current_session[:link_nonce])
    elsif type == 'fixed_ip'
      current_session[:remote_ip] ||= request.remote_ip
      current_session[:last_ip_token_requested] = DateTime.now.iso8601
    elsif type == 'expiring'
      current_session[:last_token_requested] = DateTime.now.iso8601
    else
      raise StandardError, "Unsupported link_nonce_type: '#{type}'"
    end

    session_cryptor.encrypt_and_sign(payload.to_json)
  end
end


148
149
150
# File 'lib/panda_pal/helpers/session_replacement.rb', line 148

def link_nonce_type
  self.class.link_nonce_type
end


108
109
110
# File 'lib/panda_pal/helpers/session_replacement.rb', line 108

def link_with_session_to(*args, **kwargs)
  helpers.link_to url_with_session(*args, **kwargs)
end

#redirect_with_session_to(*args, **kwargs) ⇒ Object

Redirect with the session key intact. In production, handle this by adding a one-time use encrypted token to the URL. Keeping it in the URL in development means that it plays nicely with webpack-dev-server live reloading (otherwise you get an access error everytime it tries to live reload).



104
105
106
# File 'lib/panda_pal/helpers/session_replacement.rb', line 104

def redirect_with_session_to(*args, **kwargs)
  redirect_to url_with_session(*args, **kwargs)
end

#save_sessionObject



32
33
34
# File 'lib/panda_pal/helpers/session_replacement.rb', line 32

def save_session
  current_session.try(:save)
end

#session_changed?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/panda_pal/helpers/session_replacement.rb', line 83

def session_changed?
  current_session.changed? && current_session.changes[:data].present?
end

#session_expiration_period_minutesObject



152
153
154
# File 'lib/panda_pal/helpers/session_replacement.rb', line 152

def session_expiration_period_minutes
  15
end

#session_url_for(*args, **kwargs) ⇒ Object



112
113
114
# File 'lib/panda_pal/helpers/session_replacement.rb', line 112

def session_url_for(*args, **kwargs)
  url_for(build_session_url_params(*args, **kwargs))
end

#start_panda_session!Object



36
37
38
39
# File 'lib/panda_pal/helpers/session_replacement.rb', line 36

def start_panda_session!
  raise "Session already started" if @current_session.present?
  @current_session = PandaPal::Session.new(panda_pal_organization_id: current_organization&.id)
end

#url_with_session(location, *args, route_context: self, **kwargs) ⇒ Object



116
117
118
# File 'lib/panda_pal/helpers/session_replacement.rb', line 116

def url_with_session(location, *args, route_context: self, **kwargs)
  route_context.send(location, *build_session_url_params(*args, **kwargs))
end

#verify_authenticity_tokenObject



91
92
93
94
95
96
# File 'lib/panda_pal/helpers/session_replacement.rb', line 91

def verify_authenticity_token
  # No need to check CSRF when no cookies were sent. This fixes CSRF failures in Browsers
  # that restrict Cookie setting within an IFrame.
  return unless request.cookies.keys.length > 0
  super
end