rage-rb 1.19.0 → 1.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/rage/cable/cable.rb +28 -0
- data/lib/rage/configuration.rb +19 -0
- data/lib/rage/cookies.rb +89 -0
- data/lib/rage/logger/logger.rb +1 -7
- data/lib/rage/session.rb +64 -3
- data/lib/rage/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80ca2fffb3bfe313c4be9218461d8346872ea1384472e74ed0236ece99288cfa
|
|
4
|
+
data.tar.gz: e516241ce7ffa73973b22e4abffeeb40aa0cba342d3566e3517549de979dddf6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b3ea8087b89085a05946a6efd296d3d0bae2f40184356b41d17a49f62a1ad348a0ee4d0295694e6de845465ea004d9d2fb710e0d04316c132533952d9164fae
|
|
7
|
+
data.tar.gz: 8bf64fcb40ed0beccc1f975bec376ebeeadfe84e815e10e801b69ab8820d1ddbaf8b6c87bb3bcbab04e421376b963ee905bfcf13a44443c5391a3b3fb73e30d7
|
data/CHANGELOG.md
CHANGED
data/lib/rage/cable/cable.rb
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# `Rage::Cable` provides built-in WebSocket support for Rage apps, similar to Action Cable in Rails. It lets you mount a separate WebSocket application, define channels and connections, subscribe clients to named streams, and broadcast messages in real time.
|
|
5
|
+
#
|
|
6
|
+
# Define a channel:
|
|
7
|
+
# ```ruby
|
|
8
|
+
# class ChatChannel < Rage::Cable::Channel
|
|
9
|
+
# def subscribed
|
|
10
|
+
# stream_from "chat"
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# def receive(data)
|
|
14
|
+
# puts "Received message: #{data['message']}"
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
# ```
|
|
18
|
+
#
|
|
19
|
+
# Mount the Cable application:
|
|
20
|
+
# ```ruby
|
|
21
|
+
# Rage.routes.draw do
|
|
22
|
+
# mount Rage::Cable.application, at: "/cable"
|
|
23
|
+
# end
|
|
24
|
+
# ```
|
|
25
|
+
#
|
|
26
|
+
# Broadcast a message to a stream:
|
|
27
|
+
# ```ruby
|
|
28
|
+
# Rage.cable.broadcast("chat", { message: "Hello, world!" })
|
|
29
|
+
# ```
|
|
30
|
+
#
|
|
3
31
|
module Rage::Cable
|
|
4
32
|
# Create a new Cable application.
|
|
5
33
|
#
|
data/lib/rage/configuration.rb
CHANGED
|
@@ -203,6 +203,14 @@ class Rage::Configuration
|
|
|
203
203
|
end
|
|
204
204
|
# @!endgroup
|
|
205
205
|
|
|
206
|
+
# @!group Session Configuration
|
|
207
|
+
# Allows configuring session settings.
|
|
208
|
+
# @return [Rage::Configuration::Session]
|
|
209
|
+
def session
|
|
210
|
+
@session ||= Session.new
|
|
211
|
+
end
|
|
212
|
+
# @!endgroup
|
|
213
|
+
|
|
206
214
|
# @private
|
|
207
215
|
def internal
|
|
208
216
|
@internal ||= Internal.new
|
|
@@ -773,6 +781,17 @@ class Rage::Configuration
|
|
|
773
781
|
end
|
|
774
782
|
end
|
|
775
783
|
|
|
784
|
+
class Session
|
|
785
|
+
# @!attribute key
|
|
786
|
+
# Specify the name of the session cookie.
|
|
787
|
+
# @return [String]
|
|
788
|
+
# @example Change the session cookie name
|
|
789
|
+
# Rage.configure do
|
|
790
|
+
# config.session.key = "_myapp_session"
|
|
791
|
+
# end
|
|
792
|
+
attr_accessor :key
|
|
793
|
+
end
|
|
794
|
+
|
|
776
795
|
# @private
|
|
777
796
|
class Internal
|
|
778
797
|
attr_accessor :rails_mode
|
data/lib/rage/cookies.rb
CHANGED
|
@@ -12,6 +12,92 @@ if !defined?(DomainName)
|
|
|
12
12
|
ERR
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
##
|
|
16
|
+
# Cookies provide a convenient way to store small amounts of data on the client side that persists across requests.
|
|
17
|
+
# They are commonly used for session management, personalization, and tracking user preferences.
|
|
18
|
+
#
|
|
19
|
+
# Rage cookies support both simple string-based cookies and encrypted cookies for sensitive data.
|
|
20
|
+
#
|
|
21
|
+
# To use cookies, add the `domain_name` gem to your `Gemfile`:
|
|
22
|
+
#
|
|
23
|
+
# ```bash
|
|
24
|
+
# bundle add domain_name
|
|
25
|
+
# ```
|
|
26
|
+
#
|
|
27
|
+
# Additionally, if you need to use encrypted cookies, see {Session} for setup steps.
|
|
28
|
+
#
|
|
29
|
+
# ## Usage
|
|
30
|
+
#
|
|
31
|
+
# ### Basic Cookies
|
|
32
|
+
#
|
|
33
|
+
# Read and write simple string values:
|
|
34
|
+
#
|
|
35
|
+
# ```ruby
|
|
36
|
+
# # Set a cookie
|
|
37
|
+
# cookies[:user_name] = "Alice"
|
|
38
|
+
#
|
|
39
|
+
# # Read a cookie
|
|
40
|
+
# cookies[:user_name] # => "Alice"
|
|
41
|
+
#
|
|
42
|
+
# # Delete a cookie
|
|
43
|
+
# cookies.delete(:user_name)
|
|
44
|
+
# ```
|
|
45
|
+
#
|
|
46
|
+
# ### Cookie Options
|
|
47
|
+
#
|
|
48
|
+
# Set cookies with additional options for security and control:
|
|
49
|
+
#
|
|
50
|
+
# ```ruby
|
|
51
|
+
# cookies[:user_id] = {
|
|
52
|
+
# value: "12345",
|
|
53
|
+
# expires: 1.year.from_now,
|
|
54
|
+
# secure: true,
|
|
55
|
+
# httponly: true,
|
|
56
|
+
# same_site: :lax
|
|
57
|
+
# }
|
|
58
|
+
# ```
|
|
59
|
+
#
|
|
60
|
+
# ### Encrypted Cookies
|
|
61
|
+
#
|
|
62
|
+
# Store sensitive data securely with automatic encryption:
|
|
63
|
+
#
|
|
64
|
+
# ```ruby
|
|
65
|
+
# # Set an encrypted cookie
|
|
66
|
+
# cookies.encrypted[:api_token] = "secret-token"
|
|
67
|
+
#
|
|
68
|
+
# # Read an encrypted cookie
|
|
69
|
+
# cookies.encrypted[:api_token] # => "secret-token"
|
|
70
|
+
#
|
|
71
|
+
# ```
|
|
72
|
+
#
|
|
73
|
+
# ### Permanent Cookies
|
|
74
|
+
#
|
|
75
|
+
# Create cookies that expire 20 years from now:
|
|
76
|
+
#
|
|
77
|
+
# ```ruby
|
|
78
|
+
# cookies.permanent[:remember_token] = "token-value"
|
|
79
|
+
#
|
|
80
|
+
# # Can be combined with encrypted
|
|
81
|
+
# cookies.permanent.encrypted[:user_id] = current_user.id
|
|
82
|
+
# ```
|
|
83
|
+
#
|
|
84
|
+
# ### Domain Configuration
|
|
85
|
+
#
|
|
86
|
+
# Control which domains can access your cookies:
|
|
87
|
+
#
|
|
88
|
+
# ```ruby
|
|
89
|
+
# # Specific domain
|
|
90
|
+
# cookies[:cross_domain] = { value: "data", domain: "example.com" }
|
|
91
|
+
#
|
|
92
|
+
# # All subdomains
|
|
93
|
+
# cookies[:shared] = { value: "data", domain: :all }
|
|
94
|
+
#
|
|
95
|
+
# # Multiple allowed domains
|
|
96
|
+
# cookies[:limited] = { value: "data", domain: ["app.example.com", "api.example.com"] }
|
|
97
|
+
# ```
|
|
98
|
+
#
|
|
99
|
+
# @see Session
|
|
100
|
+
#
|
|
15
101
|
class Rage::Cookies
|
|
16
102
|
# @private
|
|
17
103
|
def initialize(env, headers)
|
|
@@ -190,10 +276,13 @@ class Rage::Cookies
|
|
|
190
276
|
begin
|
|
191
277
|
box.decrypt(Base64.urlsafe_decode64(value).byteslice(2..))
|
|
192
278
|
rescue ArgumentError
|
|
279
|
+
Rage.logger.debug("Failed to decode encrypted cookie")
|
|
193
280
|
nil
|
|
194
281
|
rescue RbNaCl::CryptoError
|
|
282
|
+
Rage.logger.debug("Failed to decrypt encrypted cookie")
|
|
195
283
|
i ||= 0
|
|
196
284
|
if (box = fallback_boxes[i])
|
|
285
|
+
Rage.logger.debug("Trying to decrypt with fallback key ##{i + 1}")
|
|
197
286
|
i += 1
|
|
198
287
|
retry
|
|
199
288
|
end
|
data/lib/rage/logger/logger.rb
CHANGED
|
@@ -209,13 +209,7 @@ class Rage::Logger
|
|
|
209
209
|
RUBY
|
|
210
210
|
elsif @external_logger.is_a?(External::Dynamic)
|
|
211
211
|
# a callable object is used as a logger
|
|
212
|
-
|
|
213
|
-
@external_logger.wrapped
|
|
214
|
-
else
|
|
215
|
-
@external_logger.wrapped.method(:call)
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
parameters = Rage::Internal.build_arguments(call_method, {
|
|
212
|
+
parameters = Rage::Internal.build_arguments(@external_logger.wrapped, {
|
|
219
213
|
severity: ":#{level_name}",
|
|
220
214
|
tags: "logger[:tags].freeze",
|
|
221
215
|
context: "logger[:context].freeze",
|
data/lib/rage/session.rb
CHANGED
|
@@ -2,9 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
4
|
|
|
5
|
+
##
|
|
6
|
+
# Sessions securely store data between requests using cookies and are typically one of the most convenient and secure
|
|
7
|
+
# authentication mechanisms for browser-based clients.
|
|
8
|
+
#
|
|
9
|
+
# Rage sessions are encrypted using a secret key. This prevents clients from reading or tampering with session data.
|
|
10
|
+
#
|
|
11
|
+
# ## Setup
|
|
12
|
+
#
|
|
13
|
+
# 1. Add the required gems to your `Gemfile`:
|
|
14
|
+
#
|
|
15
|
+
# ```bash
|
|
16
|
+
# bundle add base64 domain_name rbnacl
|
|
17
|
+
# ```
|
|
18
|
+
#
|
|
19
|
+
# 2. Generate a secret key base (keep this value private and out of version control):
|
|
20
|
+
#
|
|
21
|
+
# ```bash
|
|
22
|
+
# ruby -r securerandom -e 'puts SecureRandom.hex(64)'
|
|
23
|
+
# ```
|
|
24
|
+
#
|
|
25
|
+
# 3. Configure your application to use the generated key, either via configuration:
|
|
26
|
+
#
|
|
27
|
+
# ```ruby
|
|
28
|
+
# Rage.configure do |config|
|
|
29
|
+
# config.secret_key_base = "my-secret-key"
|
|
30
|
+
# end
|
|
31
|
+
# ```
|
|
32
|
+
#
|
|
33
|
+
# or via the `SECRET_KEY_BASE` environment variable:
|
|
34
|
+
#
|
|
35
|
+
# ```bash
|
|
36
|
+
# export SECRET_KEY_BASE="my-secret-key"
|
|
37
|
+
# ```
|
|
38
|
+
#
|
|
39
|
+
# ## System Dependencies
|
|
40
|
+
#
|
|
41
|
+
# Rage sessions use libsodium (via RbNaCl) for encryption. On many Debian-based systems
|
|
42
|
+
# it is installed by default; if not, install it with:
|
|
43
|
+
#
|
|
44
|
+
# - Ubuntu / Debian:
|
|
45
|
+
#
|
|
46
|
+
# ```bash
|
|
47
|
+
# sudo apt install libsodium23
|
|
48
|
+
# ```
|
|
49
|
+
#
|
|
50
|
+
# - Fedora / RHEL / Amazon Linux:
|
|
51
|
+
#
|
|
52
|
+
# ```bash
|
|
53
|
+
# sudo yum install libsodium
|
|
54
|
+
# ```
|
|
55
|
+
#
|
|
56
|
+
# - macOS (using Homebrew):
|
|
57
|
+
#
|
|
58
|
+
# ```bash
|
|
59
|
+
# brew install libsodium
|
|
60
|
+
# ```
|
|
61
|
+
#
|
|
5
62
|
class Rage::Session
|
|
6
63
|
# @private
|
|
7
|
-
|
|
64
|
+
def self.key
|
|
65
|
+
@key ||= Rage.config.session.key&.to_sym || :"_#{Rage.root.basename.to_s.gsub(/\W/, "_").downcase}_session"
|
|
66
|
+
end
|
|
8
67
|
|
|
9
68
|
# @private
|
|
10
69
|
def initialize(cookies)
|
|
@@ -92,13 +151,15 @@ class Rage::Session
|
|
|
92
151
|
read_session.clear
|
|
93
152
|
end
|
|
94
153
|
|
|
95
|
-
@cookies[
|
|
154
|
+
@cookies[self.class.key] = { httponly: true, same_site: :lax, value: read_session.to_json }
|
|
96
155
|
end
|
|
97
156
|
|
|
98
157
|
def read_session
|
|
99
158
|
@session ||= begin
|
|
100
|
-
|
|
159
|
+
session_value = @cookies[self.class.key] || @cookies[Rack::RACK_SESSION.to_sym] || "{}"
|
|
160
|
+
JSON.parse(session_value, symbolize_names: true)
|
|
101
161
|
rescue JSON::ParserError
|
|
162
|
+
Rage.logger.debug("Failed to parse session cookie, resetting session")
|
|
102
163
|
{}
|
|
103
164
|
end
|
|
104
165
|
end
|
data/lib/rage/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rage-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.19.
|
|
4
|
+
version: 1.19.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Roman Samoilov
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-12-
|
|
10
|
+
date: 2025-12-26 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: thor
|