Class: Tina4::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/tina4/session.rb

Constant Summary collapse

DEFAULT_OPTIONS =
{
  cookie_name: "tina4_session",
  secret: nil,
  max_age: 86400,
  handler: :file,
  handler_options: {}
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, options = {}) ⇒ Session

Returns a new instance of Session.



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/tina4/session.rb', line 17

def initialize(env, options = {})
  @options = DEFAULT_OPTIONS.merge(options)
  # TINA4_SESSION_NAME — overrides cookie_name unless caller explicitly passed one.
  env_name = ENV["TINA4_SESSION_NAME"]
  if !options.key?(:cookie_name) && env_name && !env_name.empty?
    @options[:cookie_name] = env_name
  end
  @options[:secret] ||= ENV["TINA4_SECRET"] || "tina4-default-secret"
  @handler = create_handler
  @id = extract_session_id(env) || SecureRandom.hex(32)
  @data = load_session
  @modified = false
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



15
16
17
# File 'lib/tina4/session.rb', line 15

def data
  @data
end

#idObject (readonly)

Returns the value of attribute id.



15
16
17
# File 'lib/tina4/session.rb', line 15

def id
  @id
end

Instance Method Details

#[](key) ⇒ Object



31
32
33
# File 'lib/tina4/session.rb', line 31

def [](key)
  @data[key.to_s]
end

#[]=(key, value) ⇒ Object



35
36
37
38
# File 'lib/tina4/session.rb', line 35

def []=(key, value)
  @data[key.to_s] = value
  @modified = true
end

#allObject

Return all session data



82
83
84
# File 'lib/tina4/session.rb', line 82

def all
  @data.dup
end

#clearObject



45
46
47
48
# File 'lib/tina4/session.rb', line 45

def clear
  @data = {}
  @modified = true
end


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/tina4/session.rb', line 156

def cookie_header(cookie_name = nil)
  name = cookie_name || @options[:cookie_name]
  samesite = ENV["TINA4_SESSION_SAMESITE"] || "Lax"
  # HttpOnly defaults to true (existing behaviour); flip off only when explicitly false.
  httponly = !%w[false 0 no off].include?((ENV["TINA4_SESSION_HTTPONLY"] || "true").to_s.strip.downcase)
  # Secure defaults to false; flip on with truthy env var.
  secure = %w[true 1 yes on].include?((ENV["TINA4_SESSION_SECURE"] || "false").to_s.strip.downcase)

  parts = ["#{name}=#{@id}", "Path=/"]
  parts << "HttpOnly" if httponly
  parts << "Secure" if secure
  parts << "SameSite=#{samesite}"
  parts << "Max-Age=#{@options[:max_age]}"
  parts.join("; ")
end

#delete(key) ⇒ Object



40
41
42
43
# File 'lib/tina4/session.rb', line 40

def delete(key)
  @data.delete(key.to_s)
  @modified = true
end

#destroyObject



60
61
62
63
# File 'lib/tina4/session.rb', line 60

def destroy
  @handler.destroy(@id)
  @data = {}
end

#flash(key, value = nil) ⇒ Object

Flash data: set a value that is removed after next read. Call with value to set, call without value to get (and remove).



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/tina4/session.rb', line 88

def flash(key, value = nil)
  flash_key = "_flash_#{key}"
  if value.nil?
    val = @data.delete(flash_key.to_s)
    @modified = true if val
    val
  else
    @data[flash_key.to_s] = value
    @modified = true
    value
  end
end

#gc(max_lifetime = nil) ⇒ Object

Garbage collection: remove expired sessions from the handler



151
152
153
154
# File 'lib/tina4/session.rb', line 151

def gc(max_lifetime = nil)
  max_lifetime ||= @options[:max_age]
  @handler.gc(max_lifetime) if @handler.respond_to?(:gc)
end

#get(key, default = nil) ⇒ Object

Get a session value with optional default



66
67
68
# File 'lib/tina4/session.rb', line 66

def get(key, default = nil)
  @data[key.to_s] || default
end

#get_flash(key, default = nil) ⇒ Object

Get flash data by key (alias for flash(key) without value)



102
103
104
105
# File 'lib/tina4/session.rb', line 102

def get_flash(key, default = nil)
  result = flash(key)
  result.nil? ? default : result
end

#get_session_idObject

Returns the current session ID string.



131
132
133
# File 'lib/tina4/session.rb', line 131

def get_session_id
  @id
end

#has?(key) ⇒ Boolean

Check if a key exists in the session

Returns:

  • (Boolean)


77
78
79
# File 'lib/tina4/session.rb', line 77

def has?(key)
  @data.key?(key.to_s)
end

#read(session_id) ⇒ Object

Reads raw session data for a given session ID from backend storage. Returns the data hash or nil.



137
138
139
# File 'lib/tina4/session.rb', line 137

def read(session_id)
  @handler.read(session_id)
end

#regenerateObject

Regenerate the session ID while preserving data — returns new ID



108
109
110
111
112
113
114
# File 'lib/tina4/session.rb', line 108

def regenerate
  old_id = @id
  @id = SecureRandom.hex(32)
  @handler.destroy(old_id)
  @modified = true
  @id
end

#saveObject



54
55
56
57
58
# File 'lib/tina4/session.rb', line 54

def save
  return unless @modified
  @handler.write(@id, @data)
  @modified = false
end

#set(key, value) ⇒ Object

Set a session value



71
72
73
74
# File 'lib/tina4/session.rb', line 71

def set(key, value)
  @data[key.to_s] = value
  @modified = true
end

#start(session_id = nil) ⇒ Object

Start or resume a session. If session_id is given, load that session; otherwise generate a new ID. Returns the session ID string.



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/tina4/session.rb', line 118

def start(session_id = nil)
  if session_id
    @id = session_id
    @data = load_session
  else
    @id = SecureRandom.hex(32)
    @data = {}
  end
  @modified = false
  @id
end

#to_hashObject



50
51
52
# File 'lib/tina4/session.rb', line 50

def to_hash
  @data.dup
end

#write(session_id, data, ttl = nil) ⇒ Object

Writes raw session data for a given session ID to backend storage.



142
143
144
145
146
147
148
# File 'lib/tina4/session.rb', line 142

def write(session_id, data, ttl = nil)
  if ttl
    @handler.write(session_id, data, ttl)
  else
    @handler.write(session_id, data)
  end
end