|
1 | | -- a way to inject cookies into the response |
2 | | - |
3 | | -- add support for applets |
4 | | - |
5 | | - - can be implemented as separate gems |
6 | | - - can route requests to a different directory (i.e. inside the gem directory) |
7 | | - - simple way to instantiate and setup the applet |
8 | | - - as a first example, implement an auth/signin applet: |
9 | | - - session hook |
10 | | - - session persistence |
11 | | - - login page |
12 | | - - support for custom behaviour and custom workflows (2FA, signin using OTP etc.) |
13 | | - |
14 | | -- Some standard middleware: |
15 | | - |
16 | | - - request rewriter |
17 | | - - logger |
18 | | - - auth |
19 | | - - selector + terminator |
20 | | - |
21 | | - ```Ruby |
22 | | - # For the chainable DSL shown below, we need to create a custom class: |
23 | | - class Syntropy::Middleware::Selector |
24 | | - def initialize(select_proc, terminator_proc = nil) |
25 | | - @select_proc = select_proc |
26 | | - @terminator_proc = terminator_proc |
27 | | - end |
28 | | - |
29 | | - def to_proc |
30 | | - ->(req, proc) { |
31 | | - @select_proc.(req) ? @terminator_proc.(req) : proc(req) |
32 | | - } |
33 | | - end |
34 | | - |
35 | | - def terminate(&proc) |
36 | | - @terminator_proc = proc |
37 | | - end |
| 1 | + ## Routing: add support for parameter routes |
| 2 | + |
| 3 | +(following the SvelteKit convention: https://svelte.dev/docs/kit/routing): |
| 4 | + |
| 5 | +Implementation in docs repo. The routing tree should be compiled. |
| 6 | + |
| 7 | +## Support for applets |
| 8 | + |
| 9 | +- can be implemented as separate gems |
| 10 | +- can route requests to a different directory (i.e. inside the gem directory) |
| 11 | +- simple way to instantiate and setup the applet |
| 12 | +- as a first example, implement an auth/signin applet: |
| 13 | + - session hook |
| 14 | + - session persistence |
| 15 | + - login page |
| 16 | + - support for custom behaviour and custom workflows (2FA, signin using OTP etc.) |
| 17 | + |
| 18 | +Example usage: |
| 19 | + |
| 20 | +```ruby |
| 21 | +# /admin+.rb |
| 22 | +require 'syntropy/admin' |
| 23 | + |
| 24 | +export Syntropy::Admin.new(@ref, @env) |
| 25 | +``` |
| 26 | + |
| 27 | +Implementation: |
| 28 | + |
| 29 | +```ruby |
| 30 | +# syntropy-admin/lib/syntropy/admin.rb |
| 31 | +APP_ROOT = File.expand_path(File.join(__dir__, '../../app')) |
| 32 | + |
| 33 | +class Syntropy::Admin < Syntropy::App |
| 34 | + def new(mount_path, env) |
| 35 | + super(env[:machine], APP_ROOT, mount_path, env) |
38 | 36 | end |
| 37 | +end |
| 38 | +``` |
| 39 | + |
| 40 | +## Response: cookies and headers |
| 41 | + |
| 42 | +We need a way to inject cookies into the response. This probably should be done |
| 43 | +in the TP2 code: |
| 44 | + |
| 45 | +```ruby |
| 46 | +@@default_set_cookie_attr = 'HttpOnly' |
| 47 | +def self.default_set_cookie_attr=(v) |
| 48 | + @@default_set_cookie_attr = v |
| 49 | +end |
39 | 50 |
|
40 | | - def Syntropy |
41 | | - ``` |
42 | | - |
43 | | - ```Ruby |
44 | | - # a _site.rb file can be used to wrap a whole app |
45 | | - # site/_site.rb |
46 | | - |
47 | | - # this means we route according to the host header, with each |
48 | | - export Syntropy.route_by_host |
49 | | - |
50 | | - # we can also rewrite requests: |
51 | | - rewriter = Syntropy |
52 | | - .select { it.host =~ /^tolkora\.(org|com)$/ } |
53 | | - .terminate { it.redirect_permanent('https://tolkora.net') } |
54 | | - |
55 | | - # This is actuall a pretty interesting DSL design: |
56 | | - # a chain of operations that compose functions. So, we can select a |
57 | | - export rewriter.wrap(default_app) |
58 | | - |
59 | | - # composing |
60 | | - export rewriter.wrap(Syntropy.some_custom_app.wrap(app)) |
61 | | - |
62 | | - # or maybe |
63 | | - export rewriter << some_other_middleware << app |
64 | | - ``` |
65 | | - |
66 | | - |
67 | | - |
68 | | - |
69 | | -- CLI tool for setting up a site repo: |
70 | | - |
71 | | - ```bash |
72 | | - # clone a newly created repo |
73 | | - ~/repo$ git clone https://github.com/foo/bar |
74 | | - ... |
75 | | - ~/repo$ syntropy setup bar |
76 | | - |
77 | | - (syntropy banner) |
78 | | - |
79 | | - Setting up Syntropy project in /home/sharon/repo/bar: |
80 | | - |
81 | | - bar/ |
82 | | - bin/ |
83 | | - start |
84 | | - stop |
85 | | - restart |
86 | | - console |
87 | | - server |
88 | | - docker-compose.yml |
89 | | - Dockerfile |
90 | | - Gemfile |
91 | | - proxy/ |
92 | | - |
93 | | - README.md |
94 | | - site/ |
95 | | - _layout/ |
96 | | - default.rb |
97 | | - _lib/ |
98 | | - about.md |
99 | | - articles/ |
100 | | - long-form.md |
101 | | - assets/ |
102 | | - js/ |
103 | | - css/ |
104 | | - style.css |
105 | | - img/ |
106 | | - syntropy.png |
107 | | - index.rb |
108 | | - ``` |
109 | | - |
110 | | - - Some of the files might need templating, but we can maybe do without, or at |
111 | | - least make it as generic as possible. |
112 | | - |
113 | | -- `syntropy setup` steps: |
114 | | - |
115 | | - 1. Verify existence of target directory |
116 | | - 2. Copy files from Syntropy template to target directory |
117 | | - 3. Do chmod +x for bin/* |
118 | | - 4. Do bundle install in the target directory |
119 | | - 5. Show some information with regard to how to get started working with the |
120 | | - repo |
121 | | - |
122 | | -- `syntropy provision` steps: |
123 | | - |
124 | | - 1. Verify Ubuntu 22.x or higher |
125 | | - 2. Install git, docker, docker-compose |
126 | | - |
127 | | -- `syntropy deploy` steps: |
128 | | - |
129 | | - 1. Verify no uncommitted changes. |
130 | | - 2. SSH to remote machine. |
131 | | - 2.1. If not exists, clone repo |
132 | | - 2.2. Otherwise, verify remote machine repo is on same branch as local repo |
133 | | - 2.3. Do a git pull (what about credentials?) |
134 | | - 2.4. If gem bundle has changed, do a docker compose build |
135 | | - 2.5. If docker compose services are running, restart |
136 | | - 2.6. Otherwise, start services |
137 | | - 2.7. Verify service is running correctly |
| 51 | +def set_cookie(key, value, attr = @@default_set_cookie_attr) |
| 52 | + @buffered_headers ||= +'' |
| 53 | + @buffered_headers << format( |
| 54 | + "Set-Cookie: %<key>s=%<value>s; %<attr>s\n", |
| 55 | + key:, value:, attr: |
| 56 | + ) |
| 57 | +end |
| 58 | + |
| 59 | +def set_headers(headers) |
| 60 | + @buffered_headers ||= +'' |
| 61 | + @buffered_headers << format_headers(headers) |
| 62 | +end |
| 63 | + |
| 64 | +... |
| 65 | + |
| 66 | +req.set_cookie('at', 'foobar', 'SameSite=none; Secure; HttpOnly') |
| 67 | +``` |
| 68 | + |
| 69 | +## Middleware |
| 70 | + |
| 71 | +Some standard middleware: |
| 72 | + |
| 73 | +- request rewriter |
| 74 | +- logger |
| 75 | +- auth |
| 76 | +- selector + terminator |
| 77 | + |
| 78 | +```Ruby |
| 79 | +# For the chainable DSL shown below, we need to create a custom class: |
| 80 | +class Syntropy::Middleware::Selector |
| 81 | + def initialize(select_proc, terminator_proc = nil) |
| 82 | + @select_proc = select_proc |
| 83 | + @terminator_proc = terminator_proc |
| 84 | + end |
| 85 | + |
| 86 | + def to_proc |
| 87 | + ->(req, proc) { |
| 88 | + @select_proc.(req) ? @terminator_proc.(req) : proc(req) |
| 89 | + } |
| 90 | + end |
| 91 | + |
| 92 | + def terminate(&proc) |
| 93 | + @terminator_proc = proc |
| 94 | + end |
| 95 | +end |
| 96 | +``` |
| 97 | + |
| 98 | +```Ruby |
| 99 | +# a _site.rb file can be used to wrap a whole app |
| 100 | +# site/_site.rb |
| 101 | + |
| 102 | +# this means we route according to the host header, with each |
| 103 | +export Syntropy.route_by_host |
| 104 | + |
| 105 | +# we can also rewrite requests: |
| 106 | +rewriter = Syntropy |
| 107 | + .select { it.host =~ /^tolkora\.(org|com)$/ } |
| 108 | + .terminate { it.redirect_permanent('https://tolkora.net') } |
| 109 | + |
| 110 | +# This is actuall a pretty interesting DSL design: |
| 111 | +# a chain of operations that compose functions. So, we can select a |
| 112 | +export rewriter.wrap(default_app) |
| 113 | + |
| 114 | +# composing |
| 115 | +export rewriter.wrap(Syntropy.some_custom_app.wrap(app)) |
| 116 | + |
| 117 | +# or maybe |
| 118 | +export rewriter << some_other_middleware << app |
| 119 | +``` |
| 120 | + |
| 121 | +## CLI tool for setting up a site repo: |
| 122 | + |
| 123 | +```bash |
| 124 | +# clone a newly created repo |
| 125 | +~/repo$ git clone https://github.com/foo/bar |
| 126 | +... |
| 127 | +~/repo$ syntropy setup bar |
| 128 | + |
| 129 | +(syntropy banner) |
| 130 | + |
| 131 | +Setting up Syntropy project in /home/sharon/repo/bar: |
| 132 | + |
| 133 | +bar/ |
| 134 | + bin/ |
| 135 | + start |
| 136 | + stop |
| 137 | + restart |
| 138 | + console |
| 139 | + server |
| 140 | + docker-compose.yml |
| 141 | + Dockerfile |
| 142 | + Gemfile |
| 143 | + proxy/ |
| 144 | + README.md |
| 145 | + site/ |
| 146 | + _layout/ |
| 147 | + default.rb |
| 148 | + _lib/ |
| 149 | + about.md |
| 150 | + articles/ |
| 151 | + long-form.md |
| 152 | + assets/ |
| 153 | + js/ |
| 154 | + css/ |
| 155 | + style.css |
| 156 | + img/ |
| 157 | + syntropy.png |
| 158 | + index.rb |
| 159 | +``` |
| 160 | + |
| 161 | +Some of the files might need templating, but we can maybe do without, or at |
| 162 | +least make it as generic as possible. |
| 163 | + |
| 164 | +`syntropy setup` steps: |
| 165 | + |
| 166 | +1. Verify existence of target directory |
| 167 | +2. Copy files from Syntropy template to target directory |
| 168 | +3. Do chmod +x for bin/* |
| 169 | +4. Do bundle install in the target directory |
| 170 | +5. Show some information with regard to how to get started working with the |
| 171 | + repo |
| 172 | + |
| 173 | +`syntropy provision` steps: |
| 174 | + |
| 175 | +1. Verify Ubuntu 22.x or higher |
| 176 | +2. Install git, docker, docker-compose |
| 177 | + |
| 178 | +`syntropy deploy` steps: |
| 179 | + |
| 180 | +1. Verify no uncommitted changes. |
| 181 | +2. SSH to remote machine. |
| 182 | + 2.1. If not exists, clone repo |
| 183 | + 2.2. Otherwise, verify remote machine repo is on same branch as local repo |
| 184 | + 2.3. Do a git pull (what about credentials?) |
| 185 | + 2.4. If gem bundle has changed, do a docker compose build |
| 186 | + 2.5. If docker compose services are running, restart |
| 187 | + 2.6. Otherwise, start services |
| 188 | + 2.7. Verify service is running correctly |
0 commit comments