samagotchi 0.108.0 → 0.109.0
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 +33 -1
- data/docs/architecture.md +7 -2
- data/docs/configuration.md +81 -0
- data/docs/internals/participants.md +23 -6
- data/docs/internals/remote-sessions.md +6 -2
- data/lib/samagotchi/bridge.rb +25 -0
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/config.rb +4 -0
- data/lib/samagotchi/proxy_trace.rb +45 -0
- data/lib/samagotchi/session_access/local.rb +46 -10
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +231 -26
- data/lib/samagotchi/web/grants.rb +6 -3
- data/lib/samagotchi/web/info_probe.rb +5 -1
- data/lib/samagotchi/web/link_codes.rb +146 -0
- data/lib/samagotchi/web/participant_access.rb +9 -2
- data/lib/samagotchi/web/participant_review.rb +1 -1
- data/lib/samagotchi/web/participants_admin.rb +13 -6
- data/lib/samagotchi/web/proxy_gate.rb +174 -0
- data/lib/samagotchi/web/public/app.js +24 -0
- data/lib/samagotchi/web/public/auth_lost.js +76 -0
- data/lib/samagotchi/web/public/data.js +29 -5
- data/lib/samagotchi/web/public/participant.js +17 -3
- data/lib/samagotchi/web/public/token_fragment.js +57 -0
- data/lib/samagotchi/web/public_url.rb +87 -0
- data/lib/samagotchi/web/server.rb +70 -10
- data/lib/samagotchi/worker_sidecar.rb +4 -3
- metadata +7 -1
|
@@ -9,6 +9,9 @@ require "webrick"
|
|
|
9
9
|
require_relative "app"
|
|
10
10
|
require_relative "info_probe"
|
|
11
11
|
require_relative "lan"
|
|
12
|
+
require_relative "link_codes"
|
|
13
|
+
require_relative "proxy_gate"
|
|
14
|
+
require_relative "public_url"
|
|
12
15
|
require_relative "qr"
|
|
13
16
|
require_relative "running"
|
|
14
17
|
require_relative "session_hub"
|
|
@@ -58,6 +61,10 @@ module Samagotchi
|
|
|
58
61
|
# How long `chi web` waits for a server already on its port to answer.
|
|
59
62
|
PROBE_TIMEOUT = 0.3
|
|
60
63
|
|
|
64
|
+
# The raw header names next to Rack's env (ProxyGate's identity check):
|
|
65
|
+
# chi web is the only WEBrick server chi runs.
|
|
66
|
+
WEBrick::HTTPRequest.prepend(ProxyGate::RawHeaderNames) unless WEBrick::HTTPRequest < ProxyGate::RawHeaderNames
|
|
67
|
+
|
|
61
68
|
# `chi web`: one server serves every project, the scope is in the page
|
|
62
69
|
# URL. If a chi web already runs on the port, print (and with --open,
|
|
63
70
|
# open) its page for +dir+ and leave it be; else start one.
|
|
@@ -70,6 +77,7 @@ module Samagotchi
|
|
|
70
77
|
editor: Config::BY_KEY["web.editor"].default, new_token: false,
|
|
71
78
|
working_set: Config::BY_KEY["web.working_set"].default)
|
|
72
79
|
rotate_token if new_token
|
|
80
|
+
public_url = public_url_setting
|
|
73
81
|
setting = host_setting(host)
|
|
74
82
|
lan = Lan.wanted?(setting) ? Lan.choose(setting) : nil
|
|
75
83
|
host = resolve_host(setting)
|
|
@@ -85,6 +93,7 @@ module Samagotchi
|
|
|
85
93
|
end
|
|
86
94
|
puts "chi web already runs on port #{port} (pid #{found["pid"]}): #{url}"
|
|
87
95
|
puts running_lan_lines(found["lan"], port) if found["lan"]
|
|
96
|
+
puts running_public_lines(public_url) if public_url
|
|
88
97
|
puts lan_off_line(setting) if new_token && !found["lan"]
|
|
89
98
|
open_url(url) if open_browser
|
|
90
99
|
0
|
|
@@ -92,20 +101,21 @@ module Samagotchi
|
|
|
92
101
|
warn in_use_message(port)
|
|
93
102
|
1
|
|
94
103
|
else
|
|
95
|
-
if new_token && !lan
|
|
104
|
+
if new_token && !lan && !public_url
|
|
96
105
|
puts lan_off_line(setting)
|
|
97
106
|
return 0
|
|
98
107
|
end
|
|
99
108
|
# The participants' grants: never served from a store others can read.
|
|
100
109
|
Grants.check_permissions!(Grants.path)
|
|
101
110
|
if start(port: port, host: host, url: url, open_browser: open_browser, markdown: markdown, view: view,
|
|
102
|
-
annotate_presets: annotate_presets, editor: editor, lan: lan, working_set: working_set
|
|
111
|
+
annotate_presets: annotate_presets, editor: editor, lan: lan, working_set: working_set,
|
|
112
|
+
public_url: public_url)
|
|
103
113
|
0
|
|
104
114
|
else
|
|
105
115
|
1
|
|
106
116
|
end
|
|
107
117
|
end
|
|
108
|
-
rescue Lan::Error, Grants::Insecure => e
|
|
118
|
+
rescue Lan::Error, Grants::Insecure, PublicUrl::Invalid => e
|
|
109
119
|
warn "Error: #{e.message}"
|
|
110
120
|
1
|
|
111
121
|
rescue Interrupt
|
|
@@ -120,11 +130,13 @@ module Samagotchi
|
|
|
120
130
|
# @param lan [Lan::Choice, nil] also listen on this LAN address, where
|
|
121
131
|
# every request but this machine's needs the access token
|
|
122
132
|
# @param token_path [String] the LAN access token's file
|
|
133
|
+
# @param public_url [PublicUrl, nil] behind an auth proxy
|
|
134
|
+
# (web.public_url): every request needs the access token
|
|
123
135
|
# @return [Boolean] false when the port was taken (said so on stderr)
|
|
124
136
|
def self.start(port: nil, host: nil, url: nil, open_browser: false, state_dir: nil, manager: nil, markdown: false,
|
|
125
137
|
view: Config::BY_KEY["web.view"].default, annotate_presets: Config::BY_KEY["web.annotate_presets"].default, hub: nil, lan: nil,
|
|
126
138
|
editor: Config::BY_KEY["web.editor"].default, token_path: Token.path,
|
|
127
|
-
working_set: Config::BY_KEY["web.working_set"].default)
|
|
139
|
+
working_set: Config::BY_KEY["web.working_set"].default, public_url: nil)
|
|
128
140
|
config_restart_unsubscribe = ConfigFile.watch_restart_settings!(process: :web) do |message|
|
|
129
141
|
Samagotchi::Log.warn(:config, "restart_required", echo: "Warning: config: #{message}")
|
|
130
142
|
end
|
|
@@ -133,14 +145,18 @@ module Samagotchi
|
|
|
133
145
|
url ||= "http://#{url_host(host)}:#{port}/"
|
|
134
146
|
|
|
135
147
|
hub ||= SessionHub.new(state_dir: state_dir || Session.default_state_dir, manager: manager || SessionManager)
|
|
136
|
-
if lan
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
end
|
|
148
|
+
Token.load_or_create(token_path) if lan || public_url
|
|
149
|
+
lan_option = { ip: lan.ip, token: Token::Source.new(token_path) } if lan
|
|
150
|
+
public_token = Token::Source.new(token_path) if public_url
|
|
140
151
|
app = App.new(manager: manager, state_dir: state_dir, markdown: markdown, view: view,
|
|
141
|
-
annotate_presets: annotate_presets, editor: editor, hub: hub, lan: lan_option, working_set: working_set
|
|
152
|
+
annotate_presets: annotate_presets, editor: editor, hub: hub, lan: lan_option, working_set: working_set,
|
|
153
|
+
public_url: public_url, public_token: public_token)
|
|
142
154
|
Samagotchi::Log.info(:web, "start", url: "http://#{host}:#{port}", version: Samagotchi::VERSION)
|
|
143
155
|
Samagotchi::Log.info(:web, "lan", ip: lan.ip, interface: lan.interface) if lan
|
|
156
|
+
if public_url
|
|
157
|
+
Samagotchi::Log.info(:web, "public_url", origin: public_url.origin, identity_header: public_url.identity_label,
|
|
158
|
+
owner: public_url.owner ? "set" : "none")
|
|
159
|
+
end
|
|
144
160
|
# Subscribed before the first scan, which makes the first check.
|
|
145
161
|
hub.subscribe(method(:on_hub_event))
|
|
146
162
|
hub.start
|
|
@@ -151,12 +167,15 @@ module Samagotchi
|
|
|
151
167
|
record_running(running_path, port)
|
|
152
168
|
puts "Chi Web on #{url} (public: #{File.expand_path("public", __dir__)})"
|
|
153
169
|
puts lan_lines(ip: lan.ip, port: port, token: Token.read(token_path), others: lan.others, public: lan.public) if lan
|
|
170
|
+
puts public_lines(public_url, token: Token.read(token_path), codes: owner_codes(state_dir)) if public_url
|
|
154
171
|
puts "Press Ctrl-C to stop."
|
|
155
172
|
$stdout.flush # a log file isn't line-buffered
|
|
156
173
|
if open_browser
|
|
174
|
+
# With web.public_url the page opens through the proxy.
|
|
175
|
+
open_target = public_url ? public_url.link(owner_codes(state_dir).issue(kind: :owner, ttl: LinkCodes::OWNER_TTL)) : url
|
|
157
176
|
Thread.new do
|
|
158
177
|
sleep 0.8
|
|
159
|
-
open_url(
|
|
178
|
+
open_url(open_target)
|
|
160
179
|
end
|
|
161
180
|
end
|
|
162
181
|
end
|
|
@@ -224,6 +243,47 @@ module Samagotchi
|
|
|
224
243
|
raise LanListenError, e.message
|
|
225
244
|
end
|
|
226
245
|
|
|
246
|
+
# web.public_url as Server runs it, nil when unset.
|
|
247
|
+
# @raise [PublicUrl::Invalid]
|
|
248
|
+
def self.public_url_setting
|
|
249
|
+
PublicUrl.from_config(url: Samagotchi::Config.get("web.public_url"),
|
|
250
|
+
identity_header: Samagotchi::Config.get("web.proxy.identity_header"),
|
|
251
|
+
owner: Samagotchi::Config.get("web.proxy.owner"))
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# What web.public_url adds to the start lines: the proxied link (the
|
|
255
|
+
# token in its fragment) and who the owner is. On this machine the
|
|
256
|
+
# page opens through the proxy too; a direct request takes the token
|
|
257
|
+
# as Authorization: Bearer only (no cookie for 127.0.0.1, which every
|
|
258
|
+
# local port would get).
|
|
259
|
+
def self.public_lines(public_url, token:, codes: owner_codes)
|
|
260
|
+
unless token
|
|
261
|
+
return ["Proxied: #{public_url.origin}/ (no access token: its file is gone; chi web --new-token makes one)"]
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
who = if public_url.identity_header.nil? then "token only, no identity header"
|
|
265
|
+
elsif public_url.owner then "owner #{public_url.owner} by #{public_url.identity_header}, and the token"
|
|
266
|
+
else "nobody is the owner by identity: web.proxy.owner is unset"
|
|
267
|
+
end
|
|
268
|
+
code = codes.issue(kind: :owner, ttl: LinkCodes::OWNER_TTL)
|
|
269
|
+
["Proxied: #{public_url.link(code)} ← opens chi web as you once, within #{LinkCodes::OWNER_TTL / 60} minutes " \
|
|
270
|
+
"(chi web again prints a new one)",
|
|
271
|
+
" (#{who}; on this machine the page opens through the proxy too)"]
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# The owner's one-time link codes, next to the grants.
|
|
275
|
+
def self.owner_codes(state_dir = nil) = LinkCodes.for_grants(Grants.path(state_dir: state_dir))
|
|
276
|
+
|
|
277
|
+
# A second chi web, when this machine's config has web.public_url: the
|
|
278
|
+
# link from this config and the token file, never from what answered
|
|
279
|
+
# on the port.
|
|
280
|
+
def self.running_public_lines(public_url, token_path: Token.path, codes: owner_codes)
|
|
281
|
+
return ["Proxied: #{public_url.origin}/"] unless Token.read(token_path)
|
|
282
|
+
|
|
283
|
+
["Proxied: #{public_url.link(codes.issue(kind: :owner, ttl: LinkCodes::OWNER_TTL))} (once, within " \
|
|
284
|
+
"#{LinkCodes::OWNER_TTL / 60} minutes)"]
|
|
285
|
+
end
|
|
286
|
+
|
|
227
287
|
def self.host_setting(host)
|
|
228
288
|
(host || Samagotchi::Config.get("web.host")).to_s.strip
|
|
229
289
|
end
|
|
@@ -70,14 +70,15 @@ module Samagotchi
|
|
|
70
70
|
def initialize(port:, bind: nil, session_id: nil, started_at: nil, version: nil, input_format: nil, features: [],
|
|
71
71
|
epoch: nil) = super
|
|
72
72
|
|
|
73
|
-
# Written whole or not at all
|
|
74
|
-
#
|
|
73
|
+
# Written whole or not at all, readable by this user only (0600: no
|
|
74
|
+
# other account learns the worker's port from it); input_format and
|
|
75
|
+
# epoch only when they name one.
|
|
75
76
|
def write(session_dir)
|
|
76
77
|
FileUtils.mkdir_p(session_dir)
|
|
77
78
|
record = to_h.transform_keys(&:to_s)
|
|
78
79
|
record.delete("input_format") if input_format.nil?
|
|
79
80
|
record.delete("epoch") if epoch.nil?
|
|
80
|
-
AtomicFile.write(self.class.path(session_dir), "#{JSON.pretty_generate(record)}\n")
|
|
81
|
+
AtomicFile.write(self.class.path(session_dir), "#{JSON.pretty_generate(record)}\n", perm: 0o600)
|
|
81
82
|
end
|
|
82
83
|
end
|
|
83
84
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: samagotchi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.109.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Dedov
|
|
@@ -497,6 +497,7 @@ files:
|
|
|
497
497
|
- lib/samagotchi/prompt_literal_guard.rb
|
|
498
498
|
- lib/samagotchi/prompt_note.rb
|
|
499
499
|
- lib/samagotchi/prompt_warmup.rb
|
|
500
|
+
- lib/samagotchi/proxy_trace.rb
|
|
500
501
|
- lib/samagotchi/question_answer.rb
|
|
501
502
|
- lib/samagotchi/question_asked.rb
|
|
502
503
|
- lib/samagotchi/question_desk.rb
|
|
@@ -697,6 +698,7 @@ files:
|
|
|
697
698
|
- lib/samagotchi/web/grants.rb
|
|
698
699
|
- lib/samagotchi/web/info_probe.rb
|
|
699
700
|
- lib/samagotchi/web/lan.rb
|
|
701
|
+
- lib/samagotchi/web/link_codes.rb
|
|
700
702
|
- lib/samagotchi/web/markdown_renderer.rb
|
|
701
703
|
- lib/samagotchi/web/participant_access.rb
|
|
702
704
|
- lib/samagotchi/web/participant_review.rb
|
|
@@ -704,6 +706,7 @@ files:
|
|
|
704
706
|
- lib/samagotchi/web/participant_view.rb
|
|
705
707
|
- lib/samagotchi/web/participants_admin.rb
|
|
706
708
|
- lib/samagotchi/web/principal.rb
|
|
709
|
+
- lib/samagotchi/web/proxy_gate.rb
|
|
707
710
|
- lib/samagotchi/web/public/activity.js
|
|
708
711
|
- lib/samagotchi/web/public/annotate_actions.js
|
|
709
712
|
- lib/samagotchi/web/public/annotate_bar.js
|
|
@@ -711,6 +714,7 @@ files:
|
|
|
711
714
|
- lib/samagotchi/web/public/annotations.js
|
|
712
715
|
- lib/samagotchi/web/public/answer_refs.js
|
|
713
716
|
- lib/samagotchi/web/public/app.js
|
|
717
|
+
- lib/samagotchi/web/public/auth_lost.js
|
|
714
718
|
- lib/samagotchi/web/public/bubbles.js
|
|
715
719
|
- lib/samagotchi/web/public/card.js
|
|
716
720
|
- lib/samagotchi/web/public/cards_place.js
|
|
@@ -799,6 +803,7 @@ files:
|
|
|
799
803
|
- lib/samagotchi/web/public/timing.js
|
|
800
804
|
- lib/samagotchi/web/public/toast_place.js
|
|
801
805
|
- lib/samagotchi/web/public/toasts.js
|
|
806
|
+
- lib/samagotchi/web/public/token_fragment.js
|
|
802
807
|
- lib/samagotchi/web/public/tokens.css
|
|
803
808
|
- lib/samagotchi/web/public/toolkit_chip.js
|
|
804
809
|
- lib/samagotchi/web/public/turn_events.js
|
|
@@ -815,6 +820,7 @@ files:
|
|
|
815
820
|
- lib/samagotchi/web/public/working_set.js
|
|
816
821
|
- lib/samagotchi/web/public/working_set_rail.js
|
|
817
822
|
- lib/samagotchi/web/public/working_set_view.js
|
|
823
|
+
- lib/samagotchi/web/public_url.rb
|
|
818
824
|
- lib/samagotchi/web/qr.rb
|
|
819
825
|
- lib/samagotchi/web/running.rb
|
|
820
826
|
- lib/samagotchi/web/server.rb
|