utopia 1.9.5 → 1.9.6
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/.codeclimate.yml +3 -0
- data/README.md +1 -233
- data/Rakefile +5 -0
- data/documentation/pages/wiki/_listing.xnode +32 -0
- data/documentation/pages/wiki/bower-integration/content.md +25 -0
- data/documentation/pages/wiki/content.md +27 -12
- data/documentation/pages/wiki/edit.xnode +7 -0
- data/documentation/pages/wiki/middleware/content/content.md +27 -0
- data/documentation/pages/wiki/middleware/controller/content.md +62 -0
- data/documentation/pages/wiki/middleware/localization/content.md +17 -0
- data/documentation/pages/wiki/middleware/redirection/content.md +17 -0
- data/documentation/pages/wiki/middleware/session/content.md +11 -0
- data/documentation/pages/wiki/middleware/static/content.md +13 -0
- data/documentation/pages/wiki/server-setup/content.md +44 -14
- data/documentation/pages/wiki/testing/content.md +15 -0
- data/lib/utopia/command.rb +63 -4
- data/lib/utopia/setup.rb +4 -2
- data/lib/utopia/version.rb +1 -1
- data/setup/server/config/environment.yaml +1 -1
- data/setup/site/public/_static/site.css +8 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4aa4a93b7aa926a88cb796ca6f630f058bf9395
|
4
|
+
data.tar.gz: 253a3923fff1dbdd105453f75f46b8d5554b09a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dcfc6ba224e51f0b879c6c28a962737be2e13f52ec776a059916b96683cb84c3b6fcf05fde93951299d443fe12c406f6882936ff73f6851eaed49497f8ca645
|
7
|
+
data.tar.gz: 883e20396120819851979dbebc31a4fbdfc7a0309716cf334ffcd9285a6f4e254ee8d25ff1873b535b3a30529554677484529857ff75942368419daac34847cd
|
data/.codeclimate.yml
ADDED
data/README.md
CHANGED
@@ -18,8 +18,6 @@ So, Utopia exists because it suits my way of thinking about web applications, an
|
|
18
18
|
|
19
19
|
## Installation
|
20
20
|
|
21
|
-
### Local Setup
|
22
|
-
|
23
21
|
Install utopia:
|
24
22
|
|
25
23
|
$ gem install utopia
|
@@ -31,239 +29,9 @@ Create a new site:
|
|
31
29
|
$ utopia site create
|
32
30
|
$ rake
|
33
31
|
|
34
|
-
#### Bower Integration
|
35
|
-
|
36
|
-
If you create a site using the utopia generator, it includes a `.bowerrc` configuration which installs components into `public/_static/components`. To install jquery, for example:
|
37
|
-
|
38
|
-
$ bower install jquery
|
39
|
-
|
40
|
-
Then add the appropriate `<script>` tags to `pages/_page.xnode`:
|
41
|
-
|
42
|
-
<script src="/_static/components/jquery/dist/jquery.min.js" type="text/javascript"></script>
|
43
|
-
|
44
|
-
### Server Setup
|
45
|
-
|
46
|
-
Utopia can be used to set up remote sites quickly and easily.
|
47
|
-
|
48
|
-
Firstly log into your remote site using `ssh` and install utopia:
|
49
|
-
|
50
|
-
$ ssh remote
|
51
|
-
$ sudo gem install utopia
|
52
|
-
|
53
|
-
Then use the utopia command to generate a new remote site:
|
54
|
-
|
55
|
-
$ mkdir /srv/http/www.example.com
|
56
|
-
$ cd /srv/http/www.example.com
|
57
|
-
$ sudo -u http utopia server create
|
58
|
-
|
59
|
-
On the local site, you can set up a git remote:
|
60
|
-
|
61
|
-
$ git remote add production ssh://remote/srv/http/www.example.com
|
62
|
-
$ git push --set-upstream production master
|
63
|
-
|
64
|
-
When you push to the remote site, `rake deploy` will be run after the code is updated, finally, `rake restart` will be run which ideally should restart the application server.
|
65
|
-
|
66
|
-
### Passenger+Nginx Setup
|
67
|
-
|
68
|
-
Utopia works well with Passenger+Nginx. Installing Passenger+Nginx is easy:
|
69
|
-
|
70
|
-
$ ssh remote
|
71
|
-
$ sudo gem install passenger
|
72
|
-
$ passenger-install-nginx-module
|
73
|
-
|
74
|
-
Then, Nginx is configured like so:
|
75
|
-
|
76
|
-
server {
|
77
|
-
listen 80;
|
78
|
-
server_name www.example.com;
|
79
|
-
root /srv/http/www.example.com/public;
|
80
|
-
passenger_enabled on;
|
81
|
-
}
|
82
|
-
|
83
|
-
server {
|
84
|
-
listen 80;
|
85
|
-
server_name example.com;
|
86
|
-
rewrite ^ http://www.example.com$uri permanent;
|
87
|
-
}
|
88
|
-
|
89
|
-
### Arch Linux
|
90
|
-
|
91
|
-
Packages for deploying Passenger+Nginx on Arch are available in the AUR. There are issues with the official packages so please avoid them.
|
92
|
-
|
93
|
-
- [nginx-mainline-passenger](https://aur.archlinux.org/packages/nginx-mainline-passenger/)
|
94
|
-
- [passenger-nginx-module](https://aur.archlinux.org/packages/passenger-nginx-module/)
|
95
|
-
|
96
|
-
#### Compression
|
97
|
-
|
98
|
-
We suggest [enabling gzip compression](https://zoompf.com/blog/2012/02/lose-the-wait-http-compression):
|
99
|
-
|
100
|
-
gzip on;
|
101
|
-
gzip_vary on;
|
102
|
-
gzip_comp_level 6;
|
103
|
-
gzip_http_version 1.1;
|
104
|
-
gzip_proxied any;
|
105
|
-
gzip_types text/* image/svg+xml application/json application/javascript;
|
106
|
-
|
107
32
|
## Usage
|
108
33
|
|
109
|
-
|
110
|
-
|
111
|
-
- `Utopia::Static`: Serve static files efficiently.
|
112
|
-
- `Utopia::Redirection`: Redirect URL patterns and status codes.
|
113
|
-
- `Utopia::Localization`: Non-intrusive localization of resources.
|
114
|
-
- `Utopia::Controller`: Dynamic behaviour with recursive execution.
|
115
|
-
- `Utopia::Content`: XML-style template engine with powerful tag behaviours.
|
116
|
-
- `Utopia::Session`: Session storage using an encrypted cookie.
|
117
|
-
|
118
|
-
The implementation of Utopia is considered thread-safe and reentrant. However, this does not guarantee that the code YOU write will be so.
|
119
|
-
|
120
|
-
### Static
|
121
|
-
|
122
|
-
This middleware serves static files using the `mime-types` library. By default, it works with `Rack::Sendfile` and supports `ETag` based caching. Normally, you'd prefer to put static files into `public/_static` but it's also acceptable to put static content into `pages/` if it makes sense.
|
123
|
-
|
124
|
-
use Utopia::Static,
|
125
|
-
# The root path to serve files from:
|
126
|
-
root: "path/to/root",
|
127
|
-
# The mime-types to recognize/serve:
|
128
|
-
types: [:default, :xiph],
|
129
|
-
# Cache-Control header for files:
|
130
|
-
cache_control: 'public, max-age=7200'
|
131
|
-
|
132
|
-
### Redirection
|
133
|
-
|
134
|
-
A set of flexible URI rewriting middleware which includes support for string mappings, regular expressions and status codes (e.g. 404 errors).
|
135
|
-
|
136
|
-
# String (fast hash lookup) rewriting:
|
137
|
-
use Utopia::Redirection::Rewrite,
|
138
|
-
'/' => '/welcome/index'
|
139
|
-
|
140
|
-
# Redirect directories (e.g. /) to an index file (e.g. /index):
|
141
|
-
use Utopia::Redirection::DirectoryIndex,
|
142
|
-
index: 'index.html'
|
143
|
-
|
144
|
-
# Redirect (error) status codes to actual pages:
|
145
|
-
use Utopia::Redirection::Errors,
|
146
|
-
404 => '/errors/file-not-found'
|
147
|
-
|
148
|
-
### Localization
|
149
|
-
|
150
|
-
The localization middleware uses the `Accept-Language` header to guess the preferred locale out of the given options. If a request path maps to a resource, that resource is returned. Otherwise, a localized request is made.
|
151
|
-
|
152
|
-
use Utopia::Localization,
|
153
|
-
:default_locale => 'en',
|
154
|
-
:locales => ['en', 'de', 'ja', 'zh'],
|
155
|
-
:nonlocalized => ['/_static/', '/_cache/']
|
156
|
-
|
157
|
-
Somewhere further down the chain, you can localize a resource:
|
158
|
-
|
159
|
-
localization = Utopia::Localization[request]
|
160
|
-
show_welcome(localization.current_locale)
|
161
|
-
|
162
|
-
### Controller
|
163
|
-
|
164
|
-
A simple recursive controller layer which works in isolation from the view rendering middleware.
|
165
|
-
|
166
|
-
use Utopia::Controller,
|
167
|
-
# The root directory where `controller.rb` files can be found.
|
168
|
-
root: 'path/to/root',
|
169
|
-
# The base class to use for all controllers:
|
170
|
-
base: Utopia::Controller::Base
|
171
|
-
# Whether or not to cache controller classes:
|
172
|
-
cache_controllers: (RACK_ENV == :production),
|
173
|
-
|
174
|
-
A controller is a file within the root directory (or subdirectory) with the name `controller.rb`. This code is dynamically loaded into an anonymous class and executed. The default controller has only a single function:
|
175
|
-
|
176
|
-
def passthrough(request, path)
|
177
|
-
# Call one of:
|
178
|
-
|
179
|
-
# This will cause the middleware to generate a response.
|
180
|
-
# def respond!(response)
|
181
|
-
|
182
|
-
# This will cause the controller to skip the request.
|
183
|
-
# def ignore!
|
184
|
-
|
185
|
-
# Request relative redirect. Respond with a redirect to the given target.
|
186
|
-
# def redirect! (target, status = 302)
|
187
|
-
|
188
|
-
# Controller relative redirect.
|
189
|
-
# def goto!(target, status = 302)
|
190
|
-
|
191
|
-
# Respond with an error which indiciates some kind of failure.
|
192
|
-
# def fail!(error = 400, message = nil)
|
193
|
-
|
194
|
-
# Succeed the request and immediately respond.
|
195
|
-
# def succeed!(status: 200, headers: {}, **options)
|
196
|
-
# options may include content: string or body: Enumerable (as per Rack specifications
|
197
|
-
end
|
198
|
-
|
199
|
-
The controller layer can do more complex operations by prepending modules into it.
|
200
|
-
|
201
|
-
prepend Rewrite, Actions
|
202
|
-
|
203
|
-
# Extracts an Integer
|
204
|
-
rewrite.extract_prefix id: Integer do
|
205
|
-
@user = User.find_by_id(@id)
|
206
|
-
end
|
207
|
-
|
208
|
-
on 'edit' do |request, path|
|
209
|
-
if request.post?
|
210
|
-
@user.update_attributes(request[:user])
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
otherwise do |request, path|
|
215
|
-
# Executed if no specific named actions were executed.
|
216
|
-
succeed!
|
217
|
-
end
|
218
|
-
|
219
|
-
### Content
|
220
|
-
|
221
|
-
A tag based content generation system which integrates nicely with HTML5. Supports structures which separate generic page templates from dynamically generated content in an easy and consistent way.
|
222
|
-
|
223
|
-
use Utopia::Content,
|
224
|
-
cache_templates: (RACK_ENV == :production),
|
225
|
-
tags: {
|
226
|
-
'deferred' => Utopia::Tags::Deferred,
|
227
|
-
'override' => Utopia::Tags::Override,
|
228
|
-
'node' => Utopia::Tags::Node,
|
229
|
-
'environment' => Utopia::Tags::Environment.for(RACK_ENV)
|
230
|
-
}
|
231
|
-
|
232
|
-
A basic template `create.xnode` looks something like:
|
233
|
-
|
234
|
-
<page>
|
235
|
-
<heading>Create User</heading>
|
236
|
-
<form action="#">
|
237
|
-
<input name="name" />
|
238
|
-
<input type="submit" />
|
239
|
-
</form>
|
240
|
-
</page>
|
241
|
-
|
242
|
-
This template would typically be designed with supporting `_page.xnode` and `_heading.xnode` in the same directory or, more typically, somewhere further up the directory hierarchy.
|
243
|
-
|
244
|
-
### Session
|
245
|
-
|
246
|
-
The session management uses symmetric private key encryption to store data on the client and avoid tampering.
|
247
|
-
|
248
|
-
use Utopia::Session,
|
249
|
-
:expires_after => 3600,
|
250
|
-
:secret => '40 or more random characters for your secret key'
|
251
|
-
|
252
|
-
All session data is stored on the client, but it's encrypted with a salt and the secret key. It would be hard for the client to decrypt the data without the secret.
|
253
|
-
|
254
|
-
### Testing
|
255
|
-
|
256
|
-
Utopia websites include a default set of tests, and associated `rake test` tasks. These specs can test against the actual running website. By default, `simplecov` is included for coverage testing.
|
257
|
-
|
258
|
-
$ rake coverage test
|
259
|
-
|
260
|
-
my website
|
261
|
-
should have an accessible front page
|
262
|
-
|
263
|
-
Finished in 0.44849 seconds (files took 0.15547 seconds to load)
|
264
|
-
1 example, 0 failures
|
265
|
-
|
266
|
-
Coverage report generated for RSpec. 5 / 5 LOC (100.0%) covered.
|
34
|
+
There is an excellent documentation wiki included with the source code. Simply clone this repository and `rake documentation`. This documentation wiki is editable, so feel free to submit a PR with improvements.
|
267
35
|
|
268
36
|
## Contributing
|
269
37
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
<?r
|
2
|
+
|
3
|
+
case attributes[:rel]
|
4
|
+
when "utopia"
|
5
|
+
# Listing src will be relative to the base of utopia:
|
6
|
+
base_path = Utopia::default_root("../")
|
7
|
+
when "site"
|
8
|
+
# Listing src is relative to setup/site in utopia:
|
9
|
+
base_path = Utopia::default_root("../setup/site")
|
10
|
+
else
|
11
|
+
# Listing src will be relative to the path of the wiki page:
|
12
|
+
base_path = current.node.local_path(controller[:page_path])
|
13
|
+
end
|
14
|
+
|
15
|
+
if attributes[:src]
|
16
|
+
path = File.join(base_path, attributes[:src])
|
17
|
+
code = File.read(path)
|
18
|
+
else
|
19
|
+
code = content
|
20
|
+
end
|
21
|
+
|
22
|
+
escaped_code = MarkupString.new(code)
|
23
|
+
|
24
|
+
escaped_code = escaped_code.gsub(/%%([a-z]+)\{(.*?)\}/) do |match|
|
25
|
+
"<span class=\"#{$1}\">#{$2}</span>"
|
26
|
+
end
|
27
|
+
|
28
|
+
if lang = (attributes[:lang] || attributes[:brush]) ?>
|
29
|
+
<pre><code class="syntax brush-#{lang}">#{escaped_code}</code></pre>
|
30
|
+
<?r else ?>
|
31
|
+
<pre>#{escaped_code}</pre>
|
32
|
+
<?r end ?>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Bower Integration
|
2
|
+
|
3
|
+
Utopia integrates with Bower and provides a rake task to improve deployment of `dist` code.
|
4
|
+
|
5
|
+
By default, utopia includes a `.bowerrc` file which installs modules into `lib/components`. This code can then be copied into `public/_components` using `rake bower:update`.
|
6
|
+
|
7
|
+
## Installing jQuery
|
8
|
+
|
9
|
+
Firstly install jquery using bower:
|
10
|
+
|
11
|
+
$ bower install jquery
|
12
|
+
|
13
|
+
Copy the distribution scripts to `public/_components`:
|
14
|
+
|
15
|
+
$ rake bower:update
|
16
|
+
|
17
|
+
Then add the appropriate `<script>` tags to `pages/_page.xnode`:
|
18
|
+
|
19
|
+
<script src="/_components/jquery/jquery.min.js" type="text/javascript"></script>
|
20
|
+
|
21
|
+
## What does `rake bower:update` do?
|
22
|
+
|
23
|
+
This task copies only the contents of the dist directory. This ensures that you only get files intended for distribution. If the bower package doesn't have a `dist` directory, the entire contents is copied.
|
24
|
+
|
25
|
+
<listing rel="site" src="tasks/bower.rake" brush="ruby" />
|
@@ -1,12 +1,27 @@
|
|
1
|
-
# Utopia Documentation Wiki
|
2
|
-
|
3
|
-
This wiki includes documentation and examples showing how to use Utopia.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
- [
|
12
|
-
- [
|
1
|
+
# Utopia Documentation Wiki
|
2
|
+
|
3
|
+
This wiki includes documentation and examples showing how to use Utopia.
|
4
|
+
|
5
|
+
## Introduction Guide
|
6
|
+
|
7
|
+
Reading these pages in order will give you an overview of the design of Utopia, how to set it up for local development and how to deploy it.
|
8
|
+
|
9
|
+
- [Development Environment Setup](development-environment-setup/)
|
10
|
+
- [Server Setup](server-setup/)
|
11
|
+
- [Your first page](your-first-page/)
|
12
|
+
- [Installing JavaScript Libraries](bower-integration/)
|
13
|
+
- [Website Tests](testing/)
|
14
|
+
|
15
|
+
## Middleware
|
16
|
+
|
17
|
+
- [Static](middleware/static/) — Serve static files efficiently.
|
18
|
+
- [Redirection](middleware/redirection/) — Redirect URL patterns and status codes.
|
19
|
+
- [Localization](middleware/localization/) — Non-intrusive localization of resources.
|
20
|
+
- [Controller](middleware/controller/) — Flexible nested controllers with efficient behaviour.
|
21
|
+
- [Content](middleware/content/) — XML-style template engine with dynamic markup.
|
22
|
+
- [Session](middleware/session/) — Session storage using encrypted client-side cookies.
|
23
|
+
|
24
|
+
## Controller Layers
|
25
|
+
|
26
|
+
- [Controller Actions](controller/actions/)
|
27
|
+
- [Controller Rewrite](controller/rewrite/)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Content
|
2
|
+
A tag based content generation system which integrates nicely with HTML5. Supports structures which separate generic page templates from dynamically generated content in an easy and consistent way.
|
3
|
+
|
4
|
+
```ruby
|
5
|
+
use Utopia::Content,
|
6
|
+
cache_templates: (RACK_ENV == :production),
|
7
|
+
tags: {
|
8
|
+
'deferred' => Utopia::Tags::Deferred,
|
9
|
+
'override' => Utopia::Tags::Override,
|
10
|
+
'node' => Utopia::Tags::Node,
|
11
|
+
'environment' => Utopia::Tags::Environment.for(RACK_ENV)
|
12
|
+
}
|
13
|
+
```
|
14
|
+
|
15
|
+
A basic template `create.xnode` looks something like:
|
16
|
+
|
17
|
+
```trenni
|
18
|
+
<page>
|
19
|
+
<heading>Create User</heading>
|
20
|
+
<form action="#">
|
21
|
+
<input name="name" />
|
22
|
+
<input type="submit" />
|
23
|
+
</form>
|
24
|
+
</page>
|
25
|
+
```
|
26
|
+
|
27
|
+
This template would typically be designed with supporting `_page.xnode` and `_heading.xnode` in the same directory or, more typically, somewhere further up the directory hierarchy.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Controller
|
2
|
+
|
3
|
+
A simple recursive controller layer which works in isolation from the view rendering middleware.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
use Utopia::Controller,
|
7
|
+
# The root directory where `controller.rb` files can be found.
|
8
|
+
root: 'path/to/root',
|
9
|
+
# The base class to use for all controllers:
|
10
|
+
base: Utopia::Controller::Base,
|
11
|
+
# Whether or not to cache controller classes:
|
12
|
+
cache_controllers: (RACK_ENV == :production)
|
13
|
+
```
|
14
|
+
|
15
|
+
A controller is a file within the root directory (or subdirectory) with the name `controller.rb`. This code is dynamically loaded into an anonymous class and executed. The default controller has only a single function:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
def passthrough(request, path)
|
19
|
+
# Call one of:
|
20
|
+
|
21
|
+
# This will cause the middleware to generate a response.
|
22
|
+
# def respond!(response)
|
23
|
+
|
24
|
+
# This will cause the controller to skip the request.
|
25
|
+
# def ignore!
|
26
|
+
|
27
|
+
# Request relative redirect. Respond with a redirect to the given target.
|
28
|
+
# def redirect! (target, status = 302)
|
29
|
+
|
30
|
+
# Controller relative redirect.
|
31
|
+
# def goto!(target, status = 302)
|
32
|
+
|
33
|
+
# Respond with an error which indiciates some kind of failure.
|
34
|
+
# def fail!(error = 400, message = nil)
|
35
|
+
|
36
|
+
# Succeed the request and immediately respond.
|
37
|
+
# def succeed!(status: 200, headers: {}, **options)
|
38
|
+
# options may include content: string or body: Enumerable (as per Rack specifications
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
The controller layer can do more complex operations by prepending modules into it.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
prepend Rewrite, Actions
|
46
|
+
|
47
|
+
# Extracts an Integer
|
48
|
+
rewrite.extract_prefix id: Integer do
|
49
|
+
@user = User.find_by_id(@id)
|
50
|
+
end
|
51
|
+
|
52
|
+
on 'edit' do |request, path|
|
53
|
+
if request.post?
|
54
|
+
@user.update_attributes(request[:user])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
otherwise do |request, path|
|
59
|
+
# Executed if no specific named actions were executed.
|
60
|
+
succeed!
|
61
|
+
end
|
62
|
+
```
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Localization
|
2
|
+
|
3
|
+
The localization middleware uses the `Accept-Language` header to guess the preferred locale out of the given options. If a request path maps to a resource, that resource is returned. Otherwise, a localized request is made.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
use Utopia::Localization,
|
7
|
+
:default_locale => 'en',
|
8
|
+
:locales => ['en', 'de', 'ja', 'zh'],
|
9
|
+
:nonlocalized => ['/_static/', '/_cache/']
|
10
|
+
```
|
11
|
+
|
12
|
+
Somewhere further down the chain, you can localize a resource:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
localization = Utopia::Localization[request]
|
16
|
+
show_welcome(localization.current_locale)
|
17
|
+
```
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Redirection
|
2
|
+
|
3
|
+
A set of flexible URI rewriting middleware which includes support for string mappings, regular expressions and status codes (e.g. 404 errors).
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
# String (fast hash lookup) rewriting:
|
7
|
+
use Utopia::Redirection::Rewrite,
|
8
|
+
'/' => '/welcome/index'
|
9
|
+
|
10
|
+
# Redirect directories (e.g. /) to an index file (e.g. /index):
|
11
|
+
use Utopia::Redirection::DirectoryIndex,
|
12
|
+
index: 'index.html'
|
13
|
+
|
14
|
+
# Redirect (error) status codes to actual pages:
|
15
|
+
use Utopia::Redirection::Errors,
|
16
|
+
404 => '/errors/file-not-found'
|
17
|
+
```
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Session
|
2
|
+
|
3
|
+
The session management uses symmetric private key encryption to store data on the client and avoid tampering.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
use Utopia::Session,
|
7
|
+
:expires_after => 3600,
|
8
|
+
:secret => '40 or more random characters for your secret key'
|
9
|
+
```
|
10
|
+
|
11
|
+
All session data is stored on the client, but it's encrypted with a salt and the secret key. It would be hard for the client to decrypt the data without the secret.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Static
|
2
|
+
|
3
|
+
This middleware serves static files using the `mime-types` library. By default, it works with `Rack::Sendfile` and supports `ETag` based caching. Normally, you'd prefer to put static files into `public/_static` but it's also acceptable to put static content into `pages/` if it makes sense.
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
use Utopia::Static,
|
7
|
+
# The root path to serve files from:
|
8
|
+
root: "path/to/root",
|
9
|
+
# The mime-types to recognize/serve:
|
10
|
+
types: [:default, :xiph],
|
11
|
+
# Cache-Control header for files:
|
12
|
+
cache_control: 'public, max-age=7200'
|
13
|
+
```
|
@@ -1,5 +1,42 @@
|
|
1
1
|
# Server Setup
|
2
2
|
|
3
|
+
Utopia is designed to make deployment to remote servers easy.
|
4
|
+
|
5
|
+
## Deployment
|
6
|
+
|
7
|
+
The preferred method of deployment to a production server is via git. The `utopia` command assists with setup of a remote git repository on the server. It will setup a `git` `post-update` hook which will deploy the site correctly and restart passenger for that site.
|
8
|
+
|
9
|
+
To setup a server for deployment:
|
10
|
+
|
11
|
+
```bash
|
12
|
+
$ mkdir /srv/http/www.example.com
|
13
|
+
$ cd /srv/http/www.example.com
|
14
|
+
$ sudo -u http utopia server create
|
15
|
+
```
|
16
|
+
|
17
|
+
On your development machine, you should setup the git remote:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
$ git remote add production ssh://remote/srv/http/www.example.com
|
21
|
+
$ git push --set-upstream production master
|
22
|
+
```
|
23
|
+
|
24
|
+
### Default Environment
|
25
|
+
|
26
|
+
Utopia will load `config/environment.yaml` and update `ENV` before executing any code. You can set default environment values using the `utopia` command:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
$ sudo -u http utopia server environment RACK_ENV=production DATABASE_ENV=production_cluster_primary
|
30
|
+
ENV["RACK_ENV"] will default to "production" unless otherwise specified.
|
31
|
+
ENV["DATABASE_ENV"] will default to "production_cluster_primary" unless otherwise specified.
|
32
|
+
```
|
33
|
+
|
34
|
+
To set a value, write `KEY=VALUE`. To unset a key, write `KEY`.
|
35
|
+
|
36
|
+
When you run `rake` tasks or spawn a server, the values in `config/environment.yaml` will be the defaults. You can override them by manually specifying them, e.g. `DATABASE_ENV=development rake db:info`.
|
37
|
+
|
38
|
+
## Platform
|
39
|
+
|
3
40
|
The best deployment platform for Utopia is Linux. Specifically, [Arch Linux](https://www.archlinux.org/) with the following packages:
|
4
41
|
|
5
42
|
- [nginx-mainline-passenger](https://aur.archlinux.org/packages/nginx-mainline-passenger/)
|
@@ -7,7 +44,7 @@ The best deployment platform for Utopia is Linux. Specifically, [Arch Linux](htt
|
|
7
44
|
|
8
45
|
There have been issues with the official packages and thus these packages were developed and tested with Utopia deployment in mind.
|
9
46
|
|
10
|
-
|
47
|
+
### Sample Nginx Configuration
|
11
48
|
|
12
49
|
Create a configuration file for your site, e.g. `/etc/nginx/sites/www.example.com`:
|
13
50
|
|
@@ -26,21 +63,14 @@ server {
|
|
26
63
|
}
|
27
64
|
```
|
28
65
|
|
29
|
-
|
66
|
+
### Sudo Setup
|
30
67
|
|
31
|
-
|
68
|
+
Create a file `/etc/sudoers.d/http` with the following contents:
|
32
69
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
$ mkdir /srv/http/www.example.com
|
37
|
-
$ cd /srv/http/www.example.com
|
38
|
-
$ sudo -u http utopia server create
|
70
|
+
```sudoers
|
71
|
+
# Allow user samuel to check out code as user http using git:
|
72
|
+
%wheel ALL=(http) NOPASSWD: ALL
|
39
73
|
```
|
40
74
|
|
41
|
-
|
75
|
+
This allows the deploy task to correctly checkout code as user `http`.
|
42
76
|
|
43
|
-
```bash
|
44
|
-
$ git remote add production ssh://remote/srv/http/www.example.com
|
45
|
-
$ git push --set-upstream production master
|
46
|
-
```
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Testing
|
2
|
+
|
3
|
+
Utopia websites include a default set of tests, and associated `rake test` tasks. These specs can test against the actual running website. By default, `simplecov` is included for coverage testing.
|
4
|
+
|
5
|
+
```bash
|
6
|
+
$ rake coverage test
|
7
|
+
|
8
|
+
my website
|
9
|
+
should have an accessible front page
|
10
|
+
|
11
|
+
Finished in 0.44849 seconds (files took 0.15547 seconds to load)
|
12
|
+
1 example, 0 failures
|
13
|
+
|
14
|
+
Coverage report generated for RSpec. 5 / 5 LOC (100.0%) covered.
|
15
|
+
```
|
data/lib/utopia/command.rb
CHANGED
@@ -23,6 +23,8 @@ require_relative 'version'
|
|
23
23
|
require 'fileutils'
|
24
24
|
require 'find'
|
25
25
|
|
26
|
+
require 'yaml/store'
|
27
|
+
|
26
28
|
require 'samovar'
|
27
29
|
|
28
30
|
module Utopia
|
@@ -44,6 +46,18 @@ module Utopia
|
|
44
46
|
|
45
47
|
module Server
|
46
48
|
ROOT = File.join(BASE, 'server')
|
49
|
+
|
50
|
+
def self.environment(root)
|
51
|
+
# Setup config/environment.yaml according to specified options:
|
52
|
+
environment_path = File.join(root, 'config/environment.yaml')
|
53
|
+
FileUtils.mkpath File.dirname(environment_path)
|
54
|
+
|
55
|
+
store = YAML::Store.new(environment_path)
|
56
|
+
|
57
|
+
store.transaction do
|
58
|
+
yield store
|
59
|
+
end
|
60
|
+
end
|
47
61
|
end
|
48
62
|
end
|
49
63
|
|
@@ -61,21 +75,66 @@ module Utopia
|
|
61
75
|
system("git", "init", "--shared")
|
62
76
|
system("git", "config", "receive.denyCurrentBranch", "ignore")
|
63
77
|
system("git", "config", "core.worktree", destination_root)
|
64
|
-
|
65
|
-
system("cp", "-r", File.join(Setup::Server::ROOT, 'git', 'hooks'), File.join(destination_root, '.git'))
|
66
|
-
system("cp", "-r", File.join(Setup::Server::ROOT, 'config'), File.join(destination_root))
|
67
78
|
end
|
68
79
|
|
80
|
+
# Copy git hooks:
|
81
|
+
system("cp", "-r", File.join(Setup::Server::ROOT, 'git', 'hooks'), File.join(destination_root, '.git'))
|
82
|
+
|
83
|
+
# Print out helpful git remote add message:
|
69
84
|
hostname = `hostname`.chomp
|
70
85
|
puts "Now add the git remote to your local repository:\n\tgit remote add production ssh://#{hostname}#{destination_root}"
|
71
86
|
puts "Then push to it:\n\tgit push --set-upstream production master"
|
72
87
|
end
|
73
88
|
end
|
74
89
|
|
90
|
+
class Update < Samovar::Command
|
91
|
+
self.description = "Update the git hooks in an existing server repository."
|
92
|
+
|
93
|
+
def invoke(parent)
|
94
|
+
destination_root = parent.root
|
95
|
+
|
96
|
+
Dir.chdir(destination_root) do
|
97
|
+
system("git", "config", "receive.denyCurrentBranch", "ignore")
|
98
|
+
system("git", "config", "core.worktree", destination_root)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Copy git hooks:
|
102
|
+
system("cp", "-r", File.join(Setup::Server::ROOT, 'git', 'hooks'), File.join(destination_root, '.git'))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class Environment < Samovar::Command
|
107
|
+
self.description = "Update environment variables in config/environment.yaml"
|
108
|
+
|
109
|
+
many :variables, "A list of environment KEY=VALUE pairs to set."
|
110
|
+
|
111
|
+
def invoke(parent)
|
112
|
+
return if variables.empty?
|
113
|
+
|
114
|
+
destination_root = parent.root
|
115
|
+
|
116
|
+
Setup::Server.environment(destination_root) do |store|
|
117
|
+
variables.each do |variable|
|
118
|
+
key, value = variable.split('=', 2)
|
119
|
+
|
120
|
+
if value
|
121
|
+
puts "ENV[#{key.inspect}] will default to #{value.inspect} unless otherwise specified."
|
122
|
+
store[key] = value
|
123
|
+
else
|
124
|
+
puts "ENV[#{key.inspect}] will be unset unless otherwise specified."
|
125
|
+
store.delete(key)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
75
132
|
self.description = "Manage server deployments."
|
76
133
|
|
77
134
|
nested '<command>',
|
78
|
-
'create' => Create
|
135
|
+
'create' => Create,
|
136
|
+
'update' => Update,
|
137
|
+
'environment' => Environment
|
79
138
|
|
80
139
|
def invoke(parent)
|
81
140
|
@command.invoke(parent)
|
data/lib/utopia/setup.rb
CHANGED
@@ -56,8 +56,10 @@ module Utopia
|
|
56
56
|
# Load the YAML environment file:
|
57
57
|
environment = YAML.load_file(environment_path)
|
58
58
|
|
59
|
-
#
|
60
|
-
ENV.update(environment)
|
59
|
+
# We update ENV but only when it's not already set to something:
|
60
|
+
ENV.update(environment) do |name, old_value, new_value|
|
61
|
+
old_value
|
62
|
+
end
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
data/lib/utopia/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
RACK_ENV
|
1
|
+
RACK_ENV=production
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utopia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trenni
|
@@ -189,6 +189,7 @@ executables:
|
|
189
189
|
extensions: []
|
190
190
|
extra_rdoc_files: []
|
191
191
|
files:
|
192
|
+
- ".codeclimate.yml"
|
192
193
|
- ".gitignore"
|
193
194
|
- ".rspec"
|
194
195
|
- ".simplecov"
|
@@ -214,7 +215,9 @@ files:
|
|
214
215
|
- documentation/pages/errors/file-not-found.xnode
|
215
216
|
- documentation/pages/links.yaml
|
216
217
|
- documentation/pages/welcome/index.xnode
|
218
|
+
- documentation/pages/wiki/_listing.xnode
|
217
219
|
- documentation/pages/wiki/_navigation.xnode
|
220
|
+
- documentation/pages/wiki/bower-integration/content.md
|
218
221
|
- documentation/pages/wiki/content.md
|
219
222
|
- documentation/pages/wiki/controller.rb
|
220
223
|
- documentation/pages/wiki/controller/actions/content.md
|
@@ -223,8 +226,15 @@ files:
|
|
223
226
|
- documentation/pages/wiki/development-environment-setup/content.md
|
224
227
|
- documentation/pages/wiki/edit.xnode
|
225
228
|
- documentation/pages/wiki/links.yaml
|
229
|
+
- documentation/pages/wiki/middleware/content/content.md
|
230
|
+
- documentation/pages/wiki/middleware/controller/content.md
|
231
|
+
- documentation/pages/wiki/middleware/localization/content.md
|
232
|
+
- documentation/pages/wiki/middleware/redirection/content.md
|
233
|
+
- documentation/pages/wiki/middleware/session/content.md
|
234
|
+
- documentation/pages/wiki/middleware/static/content.md
|
226
235
|
- documentation/pages/wiki/server-setup/content.md
|
227
236
|
- documentation/pages/wiki/show.xnode
|
237
|
+
- documentation/pages/wiki/testing/content.md
|
228
238
|
- documentation/pages/wiki/your-first-page/content.md
|
229
239
|
- documentation/public/_components/jquery-syntax/.sass-cache/040afc1428b286fb3c50151378b349a6149698d3/jquery.syntax.core.sassc
|
230
240
|
- documentation/public/_components/jquery-syntax/.sass-cache/098642d80a1682613dca2bba6fd0a3bc9fd2bf04/jquery.syntax.layout.editor.sassc
|