diff --git a/Gemfile b/Gemfile
index 97fabcd..42c94f5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -21,14 +21,15 @@ gem 'image_processing'
gem 'mini_magick'
# Use Puma as the app server
-gem 'puma', '~> 3.0'
+gem 'puma', '~> 6.6.0'
# Use SCSS for stylesheets
-gem 'sass-rails', '~> 5.0'
+#gem 'sass-rails', '~> 6.0.0'
+gem 'dartsass-rails', '~> 0.5.1'
# TODO: ruby sass is decprecated
# Use Uglifier as compressor for JavaScript assets
-gem 'uglifier', '>= 1.3.0'
+gem 'uglifier', '>= 4.2.1'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
@@ -40,7 +41,7 @@ gem 'jquery-rails'
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-gem 'jbuilder', '~> 2.12'
+gem 'jbuilder', '~> 2.13.0'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
@@ -111,7 +112,8 @@ end
# Zurb Foundation
# https://github.com/zurb/foundation-rails
-gem 'foundation-rails', '~> 6.6'
+gem 'foundation-rails', '~> 6.9.0.0'
+gem 'autoprefixer-rails'
# Pagination
gem 'will_paginate'
@@ -137,7 +139,7 @@ gem 'font-awesome-rails'
# gem "recaptcha", require: "recaptcha/rails"
-gem 'sprockets'
+gem 'sprockets-rails'
# gem "activemodel-serializers-xml"
diff --git a/Gemfile.lock b/Gemfile.lock
index ca98737..20f02c7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,100 +1,100 @@
GEM
remote: https://rubygems.org/
specs:
- actioncable (7.1.3.4)
- actionpack (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ actioncable (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (7.1.3.4)
- actionpack (= 7.1.3.4)
- activejob (= 7.1.3.4)
- activerecord (= 7.1.3.4)
- activestorage (= 7.1.3.4)
- activesupport (= 7.1.3.4)
- mail (>= 2.7.1)
- net-imap
- net-pop
- net-smtp
- actionmailer (7.1.3.4)
- actionpack (= 7.1.3.4)
- actionview (= 7.1.3.4)
- activejob (= 7.1.3.4)
- activesupport (= 7.1.3.4)
- mail (~> 2.5, >= 2.5.4)
- net-imap
- net-pop
- net-smtp
+ actionmailbox (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
+ mail (>= 2.8.0)
+ actionmailer (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ actionview (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
+ mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
- actionpack (7.1.3.4)
- actionview (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ actionpack (7.2.2.1)
+ actionview (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
nokogiri (>= 1.8.5)
racc
- rack (>= 2.2.4)
+ rack (>= 2.2.4, < 3.2)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- actiontext (7.1.3.4)
- actionpack (= 7.1.3.4)
- activerecord (= 7.1.3.4)
- activestorage (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ useragent (~> 0.16)
+ actiontext (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (7.1.3.4)
- activesupport (= 7.1.3.4)
+ actionview (7.2.2.1)
+ activesupport (= 7.2.2.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- activejob (7.1.3.4)
- activesupport (= 7.1.3.4)
+ activejob (7.2.2.1)
+ activesupport (= 7.2.2.1)
globalid (>= 0.3.6)
- activemodel (7.1.3.4)
- activesupport (= 7.1.3.4)
- activerecord (7.1.3.4)
- activemodel (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ activemodel (7.2.2.1)
+ activesupport (= 7.2.2.1)
+ activerecord (7.2.2.1)
+ activemodel (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
timeout (>= 0.4.0)
- activestorage (7.1.3.4)
- actionpack (= 7.1.3.4)
- activejob (= 7.1.3.4)
- activerecord (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ activestorage (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
marcel (~> 1.0)
- activesupport (7.1.3.4)
+ activesupport (7.2.2.1)
base64
+ benchmark (>= 0.3)
bigdecimal
- concurrent-ruby (~> 1.0, >= 1.0.2)
+ concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
+ logger (>= 1.4.2)
minitest (>= 5.1)
- mutex_m
- tzinfo (~> 2.0)
+ securerandom (>= 0.3)
+ tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
aes_key_wrap (1.1.0)
ansi (1.5.0)
attr_required (1.0.2)
+ autoprefixer-rails (10.4.19.0)
+ execjs (~> 2)
babel-source (5.8.35)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
base64 (0.2.0)
bcrypt (3.1.20)
+ benchmark (0.4.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
- bigdecimal (3.1.8)
+ bigdecimal (3.1.9)
bindata (2.5.0)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
- bootsnap (1.18.3)
+ bootsnap (1.18.4)
msgpack (~> 1.2)
builder (3.3.0)
byebug (11.1.3)
@@ -112,12 +112,15 @@ GEM
xpath (~> 3.2)
choice (0.2.0)
coderay (1.1.3)
- concurrent-ruby (1.3.3)
- connection_pool (2.4.1)
+ concurrent-ruby (1.3.5)
+ connection_pool (2.5.0)
content_disposition (1.0.0)
crass (1.0.6)
- date (3.3.4)
- debug (1.9.2)
+ dartsass-rails (0.5.1)
+ railties (>= 6.0.0)
+ sass-embedded (~> 1.63)
+ date (3.4.1)
+ debug (1.10.0)
irb (~> 1.10)
reline (>= 0.3.8)
debug_inspector (1.2.0)
@@ -132,38 +135,44 @@ GEM
drb (2.2.1)
email_validator (2.2.4)
activemodel
- erubi (1.13.0)
- execjs (2.9.1)
- factory_bot (6.4.6)
- activesupport (>= 5.0.0)
- factory_bot_rails (6.4.3)
- factory_bot (~> 6.4)
+ erubi (1.13.1)
+ execjs (2.10.0)
+ factory_bot (6.5.1)
+ activesupport (>= 6.1.0)
+ factory_bot_rails (6.4.4)
+ factory_bot (~> 6.5)
railties (>= 5.0.0)
- faraday (2.10.0)
- faraday-net_http (>= 2.0, < 3.2)
+ faraday (2.12.2)
+ faraday-net_http (>= 2.0, < 3.5)
+ json
logger
faraday-follow_redirects (0.3.0)
faraday (>= 1, < 3)
- faraday-net_http (3.1.0)
- net-http
- fastimage (2.3.1)
- ffi (1.17.0-x86_64-linux-gnu)
- font-awesome-rails (4.7.0.8)
- railties (>= 3.2, < 8.0)
+ faraday-net_http (3.4.0)
+ net-http (>= 0.5.0)
+ fastimage (2.4.0)
+ ffi (1.17.1-x86_64-linux-gnu)
+ font-awesome-rails (4.7.0.9)
+ railties (>= 3.2, < 9.0)
formatador (1.1.0)
- foundation-rails (6.6.2.0)
+ foundation-rails (6.9.0.0)
railties (>= 3.1.0)
- sass (>= 3.3.0)
- sprockets-es6 (>= 0.9.0)
+ sassc
+ sprockets-es6
globalid (1.2.1)
activesupport (>= 6.1)
+ google-protobuf (4.29.3-x86_64-linux)
+ bigdecimal
+ rake (>= 13)
gravtastic (3.2.6)
- guard (2.18.1)
+ guard (2.19.1)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
+ logger (~> 1.6)
lumberjack (>= 1.0.12, < 2.0)
nenv (~> 0.1)
notiffany (~> 0.0)
+ ostruct (~> 0.6)
pry (>= 0.13.0)
shellany (~> 0.0)
thor (>= 0.18.1)
@@ -175,23 +184,25 @@ GEM
guard (~> 2.11)
guard-compat (~> 1.0)
hashie (5.0.0)
- i18n (1.14.5)
+ i18n (1.14.7)
concurrent-ruby (~> 1.0)
- image_processing (1.12.2)
- mini_magick (>= 4.9.5, < 5)
+ image_processing (1.14.0)
+ mini_magick (>= 4.9.5, < 6)
ruby-vips (>= 2.0.17, < 3)
- io-console (0.7.2)
- irb (1.14.0)
+ io-console (0.8.0)
+ irb (1.15.1)
+ pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
- jbuilder (2.12.0)
+ jbuilder (2.13.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
- json-jwt (1.16.6)
+ json (2.10.1)
+ json-jwt (1.16.7)
activesupport (>= 4.2)
aes_key_wrap
base64
@@ -202,8 +213,8 @@ GEM
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
- logger (1.6.0)
- loofah (2.22.0)
+ logger (1.6.5)
+ loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
lumberjack (1.2.10)
@@ -215,33 +226,34 @@ GEM
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
- mini_magick (4.13.2)
+ mini_magick (5.1.2)
+ benchmark
+ logger
mini_mime (1.1.5)
- minitest (5.24.1)
- minitest-rails (7.1.1)
+ minitest (5.25.4)
+ minitest-rails (7.2.0)
minitest (~> 5.20)
- railties (>= 7.1.0, < 8.0.0)
+ railties (>= 7.2.0, < 8.0.0)
minitest-reporters (1.7.1)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
- msgpack (1.7.2)
- mutex_m (0.2.0)
+ msgpack (1.8.0)
nenv (0.3.0)
- net-http (0.4.1)
+ net-http (0.6.0)
uri
- net-imap (0.4.14)
+ net-imap (0.5.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
- net-smtp (0.5.0)
+ net-smtp (0.5.1)
net-protocol
- nio4r (2.7.3)
- nokogiri (1.16.6-x86_64-linux)
+ nio4r (2.7.4)
+ nokogiri (1.18.2-x86_64-linux-gnu)
racc (~> 1.4)
notiffany (0.1.3)
nenv (~> 0.1)
@@ -256,7 +268,7 @@ GEM
omniauth_openid_connect (0.8.0)
omniauth (>= 1.9, < 3)
openid_connect (~> 2.2)
- openid_connect (2.3.0)
+ openid_connect (2.3.1)
activemodel
attr_required (>= 1.0.0)
email_validator
@@ -270,20 +282,26 @@ GEM
validate_url
webfinger (~> 2.0)
orm_adapter (0.5.0)
- pg (1.5.6)
- pg_search (2.3.6)
- activerecord (>= 5.2)
- activesupport (>= 5.2)
+ ostruct (0.6.1)
+ pg (1.5.9)
+ pg_search (2.3.7)
+ activerecord (>= 6.1)
+ activesupport (>= 6.1)
+ pp (0.6.2)
+ prettyprint
+ prettyprint (0.2.0)
prism (1.3.0)
- pry (0.14.2)
+ pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
- psych (5.1.2)
+ psych (5.2.3)
+ date
stringio
- public_suffix (6.0.0)
- puma (3.12.6)
- racc (1.8.0)
- rack (2.2.9)
+ public_suffix (6.0.1)
+ puma (6.6.0)
+ nio4r (~> 2.0)
+ racc (1.8.1)
+ rack (3.1.9)
rack-oauth2 (2.2.1)
activesupport
attr_required
@@ -291,30 +309,31 @@ GEM
faraday-follow_redirects
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
- rack-protection (3.2.0)
+ rack-protection (4.1.1)
base64 (>= 0.1.0)
- rack (~> 2.2, >= 2.2.4)
- rack-session (1.0.2)
- rack (< 3)
- rack-test (2.1.0)
+ logger (>= 1.6.0)
+ rack (>= 3.0.0, < 4)
+ rack-session (2.1.0)
+ base64 (>= 0.1.0)
+ rack (>= 3.0.0)
+ rack-test (2.2.0)
rack (>= 1.3)
- rackup (1.0.0)
- rack (< 3)
- webrick
- rails (7.1.3.4)
- actioncable (= 7.1.3.4)
- actionmailbox (= 7.1.3.4)
- actionmailer (= 7.1.3.4)
- actionpack (= 7.1.3.4)
- actiontext (= 7.1.3.4)
- actionview (= 7.1.3.4)
- activejob (= 7.1.3.4)
- activemodel (= 7.1.3.4)
- activerecord (= 7.1.3.4)
- activestorage (= 7.1.3.4)
- activesupport (= 7.1.3.4)
+ rackup (2.2.1)
+ rack (>= 3)
+ rails (7.2.2.1)
+ actioncable (= 7.2.2.1)
+ actionmailbox (= 7.2.2.1)
+ actionmailer (= 7.2.2.1)
+ actionpack (= 7.2.2.1)
+ actiontext (= 7.2.2.1)
+ actionview (= 7.2.2.1)
+ activejob (= 7.2.2.1)
+ activemodel (= 7.2.2.1)
+ activerecord (= 7.2.2.1)
+ activestorage (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
bundler (>= 1.15.0)
- railties (= 7.1.3.4)
+ railties (= 7.2.2.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
@@ -327,13 +346,13 @@ GEM
rails-healthcheck (1.4.0)
actionpack
railties
- rails-html-sanitizer (1.6.0)
+ rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
- nokogiri (~> 1.14)
- railties (7.1.3.4)
- actionpack (= 7.1.3.4)
- activesupport (= 7.1.3.4)
- irb
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
+ railties (7.2.2.1)
+ actionpack (= 7.2.2.1)
+ activesupport (= 7.2.2.1)
+ irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
@@ -344,43 +363,37 @@ GEM
ffi (~> 1.0)
rbs (3.8.1)
logger
- rdoc (6.7.0)
+ rdoc (6.12.0)
psych (>= 4.0.0)
- regexp_parser (2.9.2)
- reline (0.5.9)
+ regexp_parser (2.10.0)
+ reline (0.6.0)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
- rexml (3.3.1)
- strscan
- rouge (4.3.0)
+ rexml (3.4.0)
+ rouge (4.5.1)
ruby-graphviz (1.2.5)
rexml
- ruby-lsp (0.23.8)
+ ruby-lsp (0.23.10)
language_server-protocol (~> 3.17.0)
prism (>= 1.2, < 2.0)
rbs (>= 3, < 4)
sorbet-runtime (>= 0.5.10782)
ruby-progressbar (1.13.0)
- ruby-vips (2.2.1)
+ ruby-vips (2.2.3)
ffi (~> 1.12)
- rubyzip (2.3.2)
+ logger
+ rubyzip (2.4.1)
rufo (0.18.0)
- sass (3.7.4)
- sass-listen (~> 4.0.0)
- sass-listen (4.0.0)
- rb-fsevent (~> 0.9, >= 0.9.4)
- rb-inotify (~> 0.9, >= 0.9.7)
- sass-rails (5.1.0)
- railties (>= 5.2.0)
- sass (~> 3.1)
- sprockets (>= 2.8, < 4.0)
- sprockets-rails (>= 2.0, < 4.0)
- tilt (>= 1.1, < 3)
+ sass-embedded (1.83.4-x86_64-linux-gnu)
+ google-protobuf (~> 4.29)
+ sassc (2.4.0)
+ ffi (~> 1.9)
sdoc (2.6.1)
rdoc (>= 5.0)
- selenium-webdriver (4.22.0)
+ securerandom (0.4.1)
+ selenium-webdriver (4.28.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -393,46 +406,45 @@ GEM
slim (5.2.1)
temple (~> 0.10.0)
tilt (>= 2.1.0)
- slim-rails (3.6.3)
+ slim-rails (3.7.0)
actionpack (>= 3.1)
railties (>= 3.1)
slim (>= 3.0, < 6.0, != 5.0.0)
- sorbet-runtime (0.5.11798)
+ sorbet-runtime (0.5.11820)
spring (2.1.1)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
- sprockets (3.7.3)
- base64
+ sprockets (4.2.1)
concurrent-ruby (~> 1.0)
- rack (> 1, < 3)
+ rack (>= 2.2.4, < 4)
sprockets-es6 (0.9.2)
babel-source (>= 5.8.11)
babel-transpiler
sprockets (>= 3.0.0)
- sprockets-rails (3.5.1)
+ sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
- stringio (3.1.1)
- strscan (3.1.0)
+ stringio (3.1.2)
swd (2.0.3)
activesupport (>= 3)
attr_required (>= 0.0.5)
faraday (~> 2.0)
faraday-follow_redirects
temple (0.10.3)
- thor (1.3.1)
- tilt (2.4.0)
- timeout (0.4.1)
+ thor (1.3.2)
+ tilt (2.6.0)
+ timeout (0.4.3)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
- uglifier (4.2.0)
+ uglifier (4.2.1)
execjs (>= 0.3.0, < 3)
- uri (0.13.0)
+ uri (1.0.2)
+ useragent (0.16.11)
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
@@ -442,9 +454,9 @@ GEM
activesupport
faraday (~> 2.0)
faraday-follow_redirects
- webrick (1.8.1)
websocket (1.2.11)
- websocket-driver (0.7.6)
+ websocket-driver (0.7.7)
+ base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
will_paginate (4.0.1)
@@ -452,12 +464,13 @@ GEM
will_paginate (>= 3.0.3)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.6.16)
+ zeitwerk (2.7.1)
PLATFORMS
x86_64-linux
DEPENDENCIES
+ autoprefixer-rails
better_errors
binding_of_caller
bootsnap
@@ -465,17 +478,18 @@ DEPENDENCIES
bzip2-ffi
cancancan
capybara
+ dartsass-rails (~> 0.5.1)
debug
devise
factory_bot_rails
fastimage
font-awesome-rails
- foundation-rails (~> 6.6)
+ foundation-rails (~> 6.9.0.0)
gravtastic
guard-minitest
guard-rails
image_processing
- jbuilder (~> 2.12)
+ jbuilder (~> 2.13.0)
jquery-rails
listen (~> 3.5)
mini_magick
@@ -487,22 +501,21 @@ DEPENDENCIES
omniauth_openid_connect
pg
pg_search
- puma (~> 3.0)
+ puma (~> 6.6.0)
rails (~> 7.1)
rails-erd
rails-healthcheck
ruby-lsp
rufo
- sass-rails (~> 5.0)
sdoc
selenium-webdriver
shrine (~> 3.0)
slim-rails
spring
spring-watcher-listen (~> 2.0.0)
- sprockets
+ sprockets-rails
turbolinks (~> 5)
- uglifier (>= 1.3.0)
+ uglifier (>= 4.2.1)
will_paginate
will_paginate-foundation
diff --git a/app/assets/builds/application.css b/app/assets/builds/application.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/app/assets/builds/application.css
@@ -0,0 +1 @@
+
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644
index 0000000..9e0e087
--- /dev/null
+++ b/app/assets/config/manifest.js
@@ -0,0 +1,4 @@
+//= link_tree ../images
+//= link_directory ../javascripts .js
+//= link_directory ../stylesheets .css
+//= link application.js
diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss
index 3b800ff..cba0260 100644
--- a/app/assets/stylesheets/_settings.scss
+++ b/app/assets/stylesheets/_settings.scss
@@ -58,8 +58,9 @@
// 53. Title Bar
// 54. Tooltip
// 55. Top Bar
-// 56. Xy Grid
+// 57. Xy Grid
+@use "sass:color";
@import 'util/util';
// 1. Global
@@ -69,22 +70,21 @@ $global-font-size: 100%;
$global-width: rem-calc(1200);
$global-lineheight: 1.5;
$foundation-palette: (
- primary: #c70338,
- secondary: #767676,
- success: #3adb76,
- warning: #ffae00,
- alert: #cc4b37,
+ "primary": #1779ba,
+ "secondary": #767676,
+ "success": #3adb76,
+ "warning": #ffae00,
+ "alert": #cc4b37,
);
$light-gray: #e6e6e6;
$medium-gray: #cacaca;
$dark-gray: #8a8a8a;
$black: #0a0a0a;
$white: #fefefe;
-// $body-background: $white;
-$body-background: #f2f2f2;
+$body-background: $white;
$body-font-color: $black;
-$body-font-family: 'Droid Sans', sans-serif;
-// $body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
+$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
+$body-safe-padding: false;
$body-antialiased: true;
$global-margin: 1rem;
$global-padding: 1rem;
@@ -92,8 +92,7 @@ $global-position: 1rem;
$global-weight-normal: normal;
$global-weight-bold: bold;
$global-radius: 0;
-$global-menu-padding: 0.3rem 0.5rem;
-// $global-menu-padding: 0.7rem 1rem;
+$global-menu-padding: 0.7rem 1rem;
$global-menu-nested-margin: 1rem;
$global-text-direction: ltr;
$global-flexbox: true;
@@ -101,18 +100,27 @@ $global-prototype-breakpoints: false;
$global-button-cursor: auto;
$global-color-pick-contrast-tolerance: 0;
$print-transparent-backgrounds: true;
+$print-hrefs: true;
@include add-foundation-colors;
// 2. Breakpoints
// --------------
+$-zf-size: null;
$breakpoints: (
- small: 0,
- medium: 640px,
- large: 1024px,
- xlarge: 1200px,
- xxlarge: 1440px,
+ "small": 0,
+ "medium": 640px,
+ "large": 1024px,
+ "xlarge": 1200px,
+ "xxlarge": 1440px,
+);
+$breakpoints-hidpi: (
+ "hidpi-1": 1,
+ "hidpi-1-5": 1.5,
+ "hidpi-2": 2,
+ "retina": 2,
+ "hidpi-3": 3
);
$print-breakpoint: large;
$breakpoint-classes: (small medium large);
@@ -143,19 +151,19 @@ $header-margin-bottom: 0.5rem;
$header-styles: (
small: (
'h1': ('font-size': 24),
- 'h2': ('font-size': 16),
- 'h3': ('font-size': 14),
- 'h4': ('font-size': 13),
- 'h5': ('font-size': 12),
- 'h6': ('font-size': 11),
+ 'h2': ('font-size': 20),
+ 'h3': ('font-size': 19),
+ 'h4': ('font-size': 18),
+ 'h5': ('font-size': 17),
+ 'h6': ('font-size': 16),
),
medium: (
- 'h1': ('font-size': 40),
- 'h2': ('font-size': 32),
- 'h3': ('font-size': 28),
- 'h4': ('font-size': 26),
- 'h5': ('font-size': 24),
- 'h6': ('font-size': 22),
+ 'h1': ('font-size': 48),
+ 'h2': ('font-size': 40),
+ 'h3': ('font-size': 31),
+ 'h4': ('font-size': 25),
+ 'h5': ('font-size': 20),
+ 'h6': ('font-size': 16),
),
);
$header-text-rendering: optimizeLegibility;
@@ -164,12 +172,7 @@ $header-small-font-color: $medium-gray;
$paragraph-lineheight: 1.6;
$paragraph-margin-bottom: 1rem;
$paragraph-text-rendering: optimizeLegibility;
-$code-color: $black;
-$code-font-family: $font-family-monospace;
-$code-font-weight: $global-weight-normal;
-$code-background: $light-gray;
-$code-border: 1px solid $medium-gray;
-$code-padding: rem-calc(2 5 1);
+$enable-code-inline: true;
$anchor-color: $primary-color;
$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
$anchor-text-decoration: none;
@@ -189,9 +192,7 @@ $defnlist-term-margin-bottom: 0.3rem;
$blockquote-color: $dark-gray;
$blockquote-padding: rem-calc(9 20 0 19);
$blockquote-border: 1px solid $medium-gray;
-$cite-font-size: rem-calc(13);
-$cite-color: $dark-gray;
-$cite-pseudo-content: '\2014 \0020';
+$enable-cite-block: true;
$keystroke-font: $font-family-monospace;
$keystroke-color: $black;
$keystroke-background: $light-gray;
@@ -210,6 +211,17 @@ $subheader-font-weight: $global-weight-normal;
$subheader-margin-top: 0.2rem;
$subheader-margin-bottom: 0.5rem;
$stat-font-size: 2.5rem;
+$cite-color: $dark-gray;
+$cite-font-size: rem-calc(13);
+$cite-pseudo-content: '\2014 \0020';
+$code-color: $black;
+$code-font-family: $font-family-monospace;
+$code-font-weight: $global-weight-normal;
+$code-background: $light-gray;
+$code-border: 1px solid $medium-gray;
+$code-padding: rem-calc(2 5 1);
+$code-block-padding: 1rem;
+$code-block-margin-bottom: 1.5rem;
// 6. Abide
// --------
@@ -227,6 +239,8 @@ $input-error-font-weight: $global-weight-bold;
$accordion-background: $white;
$accordion-plusminus: true;
+$accordion-plus-content: '\002B';
+$accordion-minus-content: '\2013';
$accordion-title-font-size: rem-calc(12);
$accordion-item-color: $primary-color;
$accordion-item-background-hover: $light-gray;
@@ -282,6 +296,7 @@ $breadcrumbs-item-separator-color: $medium-gray;
// ----------
$button-font-family: inherit;
+$button-font-weight: null;
$button-padding: 0.85em 1em;
$button-margin: 0 0 $global-margin 0;
$button-fill: solid;
@@ -289,8 +304,8 @@ $button-background: $primary-color;
$button-background-hover: scale-color($button-background, $lightness: -15%);
$button-color: $white;
$button-color-alt: $black;
-//$button-radius: $global-radius;
-$button-radius: 0.5rem;
+$button-radius: $global-radius;
+$button-border: 1px solid transparent;
$button-hollow-border-width: 1px;
$button-sizes: (
tiny: 0.6rem,
@@ -303,6 +318,7 @@ $button-opacity-disabled: 0.25;
$button-background-hover-lightness: -20%;
$button-hollow-hover-lightness: -50%;
$button-transition: background-color 0.25s ease-out, color 0.25s ease-out;
+$button-responsive-expanded: false;
// 12. Button Group
// ----------------
@@ -320,7 +336,11 @@ $callout-background: $white;
$callout-background-fade: 85%;
$callout-border: 1px solid rgba($black, 0.25);
$callout-margin: 0 0 1rem 0;
-$callout-padding: 1rem;
+$callout-sizes: (
+ small: 0.5rem,
+ default: 1rem,
+ large: 3rem,
+);
$callout-font-color: $body-font-color;
$callout-font-color-alt: $body-background;
$callout-radius: $global-radius;
@@ -342,6 +362,8 @@ $card-margin-bottom: $global-margin;
// ----------------
$closebutton-position: right top;
+$closebutton-z-index: 10;
+$closebutton-default-size: medium;
$closebutton-offset-horizontal: (
small: 0.66rem,
medium: 1rem,
@@ -394,8 +416,8 @@ $dropdownmenu-arrow-color: $anchor-color;
$dropdownmenu-arrow-size: 6px;
$dropdownmenu-arrow-padding: 1.5rem;
$dropdownmenu-min-width: 200px;
-$dropdownmenu-background: $white;
-$dropdownmenu-submenu-background: $dropdownmenu-background;
+$dropdownmenu-background: null;
+$dropdownmenu-submenu-background: $white;
$dropdownmenu-padding: $global-menu-padding;
$dropdownmenu-nested-margin: 0;
$dropdownmenu-submenu-padding: $dropdownmenu-padding;
@@ -442,7 +464,7 @@ $input-background-focus: $white;
$input-background-disabled: $light-gray;
$input-border: 1px solid $medium-gray;
$input-border-focus: 1px solid $dark-gray;
-$input-padding: $form-spacing / 2;
+$input-padding: $form-spacing * 0.5;
$input-shadow: inset 0 1px 2px rgba($black, 0.1);
$input-shadow-focus: 0 0 5px $medium-gray;
$input-cursor-disabled: not-allowed;
@@ -477,9 +499,9 @@ $menu-nested-margin: $global-menu-nested-margin;
$menu-items-padding: $global-menu-padding;
$menu-simple-margin: 1rem;
$menu-item-color-active: $white;
+$menu-item-color-alt-active: $black;
$menu-item-background-active: get-color(primary);
$menu-icon-spacing: 0.25rem;
-$menu-item-background-hover: $light-gray;
$menu-state-back-compat: true;
$menu-centered-back-compat: true;
$menu-icons-back-compat: true;
@@ -549,6 +571,8 @@ $pagination-ellipsis-color: $black;
$pagination-mobile-items: false;
$pagination-mobile-current-item: false;
$pagination-arrows: true;
+$pagination-arrow-previous: '\00AB';
+$pagination-arrow-next: '\00BB';
// 28. Progress Bar
// ----------------
@@ -670,8 +694,7 @@ $prototype-separator-margin-top: $global-margin;
// --------------------
$prototype-shadow-breakpoints: $global-prototype-breakpoints;
-$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),
- 0 2px 10px 0 rgba(0,0,0,.12);
+$prototype-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
// 41. Prototype Sizing
// --------------------
@@ -759,7 +782,9 @@ $slider-radius: $global-radius;
// ----------
$switch-background: $medium-gray;
+$switch-background-focus: scale-color($switch-background, $lightness: -10%);
$switch-background-active: $primary-color;
+$switch-background-active-focus: scale-color($switch-background-active, $lightness: -15%);
$switch-height: 2rem;
$switch-height-tiny: 1.5rem;
$switch-height-small: 1.75rem;
@@ -770,6 +795,8 @@ $switch-paddle-background: $white;
$switch-paddle-offset: 0.25rem;
$switch-paddle-radius: $global-radius;
$switch-paddle-transition: all 0.25s ease-out;
+$switch-opacity-disabled: 0.5;
+$switch-cursor-disabled: not-allowed;
// 50. Table
// ---------
@@ -779,15 +806,15 @@ $table-color-scale: 5%;
$table-border: 1px solid smart-scale($table-background, $table-color-scale);
$table-padding: rem-calc(8 10 10);
$table-hover-scale: 2%;
-$table-row-hover: darken($table-background, $table-hover-scale);
-$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
+$table-row-hover: color.adjust($table-background, $lightness: -$table-hover-scale);
+$table-row-stripe-hover: color.adjust($table-background, $lightness: -($table-color-scale + $table-hover-scale));
$table-is-striped: true;
$table-striped-background: smart-scale($table-background, $table-color-scale);
$table-stripe: even;
-$table-head-background: smart-scale($table-background, $table-color-scale / 2);
-$table-head-row-hover: darken($table-head-background, $table-hover-scale);
+$table-head-background: smart-scale($table-background, $table-color-scale * 0.5);
+$table-head-row-hover: color.adjust($table-head-background, $lightness: -$table-hover-scale);
$table-foot-background: smart-scale($table-background, $table-color-scale);
-$table-foot-row-hover: darken($table-foot-background, $table-hover-scale);
+$table-foot-row-hover: color.adjust($table-foot-background, $lightness: -$table-hover-scale);
$table-head-font-color: $body-font-color;
$table-foot-font-color: $body-font-color;
$show-header-for-stacked: false;
@@ -804,7 +831,6 @@ $tab-active-color: $primary-color;
$tab-item-font-size: rem-calc(12);
$tab-item-background-hover: $white;
$tab-item-padding: 1.25rem 1.5rem;
-$tab-expand-max: 6;
$tab-content-background: $white;
$tab-content-border: $light-gray;
$tab-content-color: $body-font-color;
@@ -813,7 +839,7 @@ $tab-content-padding: 1rem;
// 52. Thumbnail
// -------------
-$thumbnail-border: solid 4px $white;
+$thumbnail-border: 4px solid $white;
$thumbnail-margin-bottom: $global-margin;
$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
@@ -849,23 +875,22 @@ $tooltip-radius: $global-radius;
// 55. Top Bar
// -----------
-$topbar-padding: 0;
-// $topbar-background: $light-gray;
-$topbar-background: #d8d8d8;
+$topbar-padding: 0.5rem;
+$topbar-background: $light-gray;
$topbar-submenu-background: $topbar-background;
$topbar-title-spacing: 0.5rem 1rem 0.5rem 0;
$topbar-input-width: 200px;
$topbar-unstack-breakpoint: medium;
-// 56. Xy Grid
+// 57. Xy Grid
// -----------
$xy-grid: true;
$grid-container: $global-width;
$grid-columns: 12;
$grid-margin-gutters: (
- small: 20px,
- medium: 30px
+ "small": 20px,
+ "medium": 30px
);
$grid-padding-gutters: $grid-margin-gutters;
$grid-container-padding: $grid-padding-gutters;
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 2bcc98b..1b79845 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -9,6 +9,8 @@
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
+//= require foundation_and_overrides
+
*= require foundation_and_overrides
*= require font-awesome
*= require my_styles
diff --git a/app/assets/stylesheets/browserslist b/app/assets/stylesheets/browserslist
new file mode 100644
index 0000000..6019618
--- /dev/null
+++ b/app/assets/stylesheets/browserslist
@@ -0,0 +1,4 @@
+last 2 versions
+ie >= 9
+Android >= 2.3
+ios >= 7
diff --git a/app/controllers/packages_controller.rb b/app/controllers/packages_controller.rb
index add8d0a..c1a19ae 100644
--- a/app/controllers/packages_controller.rb
+++ b/app/controllers/packages_controller.rb
@@ -341,7 +341,7 @@ class PackagesController < ApplicationController
# Return packages matching the criteria given by parameters
def query_packages
- packages = Package.order(visits: :desc)
+ packages = Package #.order(visits: :desc)
# text search
if params[:search].present?
@@ -352,7 +352,7 @@ class PackagesController < ApplicationController
case params[:show]
when 'with'
# Enrich the result with the screenshots readable by the current user (CanCanCan)
- packages = packages.with_screenshots
+ packages = packages.with_public_screenshots
logger.debug 'Limiting packages to those with screenshots'
when 'without'
packages = packages.without_screenshots
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index d2dca58..2935bb2 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -4,12 +4,13 @@ class WelcomeController < ApplicationController
def home
@newest_upload = Screenshot.where(approved: true).first
- @most_popular_package = Package.with_screenshots.order(visits: :desc).first
+ #@most_popular_package = Package.with_screenshots.order(visits: :desc).first
+ @random_pick = Package.with_public_screenshots.order("RANDOM()").first
@package_count = Package.count
# Get up 100 screenshots where the packages have the most visits
- query = Package.without_screenshots.order(visits: :desc)
+ query = Package.without_screenshots #.order(visits: :desc)
count = query.count
random_offset = rand( [100, count].min )
@most_wanted_package = query.offset(random_offset).first
diff --git a/app/models/package.rb b/app/models/package.rb
index d8775ba..f4c7169 100644
--- a/app/models/package.rb
+++ b/app/models/package.rb
@@ -51,6 +51,13 @@ class Package < ApplicationRecord
where(id: subselect)
end
+ # Return a query of all packages that have approved screenshots
+ def self.with_public_screenshots
+ # Query for all packages who's ID appears in a screenshot's "package_id" field
+ subselect = Screenshot.visible.approved.select(:package_id)
+ where(id: subselect)
+ end
+
# Return a list of packages that have screenshots to be moderated
def self.need_moderation
Package.joins(:screenshots).where('screenshots.approved=false').distinct(:name)
diff --git a/app/models/screenshot.rb b/app/models/screenshot.rb
index df71257..b8ee8da 100644
--- a/app/models/screenshot.rb
+++ b/app/models/screenshot.rb
@@ -8,6 +8,7 @@ class Screenshot < ApplicationRecord
default_scope { order(approved: :asc, hidden: :asc, created_at: :desc) }
scope :approved, -> { where(approved: true) }
+ scope :visible, -> { where(hidden: false) }
# Shrine
include ImageUploader::Attachment(:simage) # adds an `simage` virtual attribute
diff --git a/app/views/layouts/application.html.erb___ b/app/views/layouts/application.html.erb___
new file mode 100644
index 0000000..cd60004
--- /dev/null
+++ b/app/views/layouts/application.html.erb___
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ <%= content_for?(:title) ? yield(:title) : "Untitled" %>
+
+ <%= stylesheet_link_tag "application" %>
+ <%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
+ <%= csrf_meta_tags %>
+
+
+
+
+ <%= yield %>
+
+
+
diff --git a/app/views/welcome/home.slim b/app/views/welcome/home.slim
index 29cc942..83f8ab1 100644
--- a/app/views/welcome/home.slim
+++ b/app/views/welcome/home.slim
@@ -39,19 +39,19 @@
.small-12.medium-4.cell
- h2.text-center Most popular
+ h2.text-center Random pick
.pkgcard
.image
- - if @most_popular_package
- a href=package_path(@most_popular_package.name)
- = small_img(@most_popular_package.screenshots.first)
+ - if @random_pick
+ a href=package_path(@random_pick.name)
+ = small_img(@random_pick.screenshots.first)
- else
'No uploaded screenshots yet.
.text
strong
- =@most_popular_package.name
+ =@random_pick.name
' :
- =@most_popular_package.description
+ =@random_pick.description
.small-12.medium-4.cell
h2.text-center Your help needed
diff --git a/bin/sass b/bin/sass
deleted file mode 100755
index ef9f699..0000000
--- a/bin/sass
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-#
-# This file was generated by Bundler.
-#
-# The application 'sass' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
- Pathname.new(__FILE__).realpath)
-
-require "rubygems"
-require "bundler/setup"
-
-load Gem.bin_path("sass", "sass")
diff --git a/bin/sass-convert b/bin/sass-convert
deleted file mode 100755
index 13936f1..0000000
--- a/bin/sass-convert
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-#
-# This file was generated by Bundler.
-#
-# The application 'sass-convert' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require "pathname"
-ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
- Pathname.new(__FILE__).realpath)
-
-require "rubygems"
-require "bundler/setup"
-
-load Gem.bin_path("sass", "sass-convert")
diff --git a/bin/setup b/bin/setup
index ec47b79..ce0ec18 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1,11 +1,11 @@
#!/usr/bin/env ruby
require "fileutils"
-# path to your application root.
APP_ROOT = File.expand_path("..", __dir__)
+APP_NAME = "debshots"
def system!(*args)
- system(*args) || abort("\n== Command #{args} failed ==")
+ system(*args, exception: true)
end
FileUtils.chdir APP_ROOT do
@@ -30,4 +30,8 @@ FileUtils.chdir APP_ROOT do
puts "\n== Restarting application server =="
system! "bin/rails restart"
+
+ # puts "\n== Configuring puma-dev =="
+ # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}"
+ # system "curl -Is https://#{APP_NAME}.test/up | head -n 1"
end
diff --git a/config/application.rb b/config/application.rb
index 531b8e3..ee13544 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,6 +1,6 @@
-require_relative 'boot'
+require_relative "boot"
-require 'rails/all'
+require "rails/all"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
@@ -11,7 +11,10 @@ module Debshots
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.1
- #config.active_support.cache_format_version = 7.1
+ # Please, add to the `ignore` list any other `lib` subdirectories that do
+ # not contain `.rb` files, or that should not be reloaded or eager loaded.
+ # Common ones are `templates`, `generators`, or `middleware`, for example.
+ config.autoload_lib(ignore: %w[assets tasks])
# Configuration for the application, engines, and railties goes here.
#
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 0013462..3beb0d0 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -6,7 +6,7 @@ Rails.application.configure do
# In the development environment your application's code is reloaded any time
# it changes. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
- config.cache_classes = false
+ config.enable_reloading = true
# Do not eager load code on boot.
config.eager_load = false
@@ -14,16 +14,17 @@ Rails.application.configure do
# Show full error reports.
config.consider_all_requests_local = true
+ # Enable server timing.
+ config.server_timing = true
+
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
- if Rails.root.join('tmp', 'caching-dev.txt').exist?
+ if Rails.root.join("tmp/caching-dev.txt").exist?
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :memory_store
- config.public_file_server.headers = {
- 'Cache-Control' => "public, max-age=#{2.days.to_i}"
- }
+ config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" }
else
config.action_controller.perform_caching = false
@@ -43,10 +44,13 @@ Rails.application.configure do
config.action_mailer.default_url_options = {
host: "screenshots.debian.net",
protocol: 'https'
- }
+ # Disable caching for Action Mailer templates even if Action Controller
+ # caching is enabled.
config.action_mailer.perform_caching = false
+ config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
+
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
@@ -62,10 +66,8 @@ Rails.application.configure do
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
- # Debug mode disables concatenation and preprocessing of assets.
- # This option may cause significant delays in view rendering with a large
- # number of complex assets.
- config.assets.debug = true
+ # Highlight code that enqueued background job in logs.
+ config.active_job.verbose_enqueue_logs = true
# Suppress logger output for asset requests.
config.assets.quiet = true
@@ -100,4 +102,7 @@ Rails.application.configure do
# Uncomment if you wish to allow Action Cable access from any origin.
# config.action_cable.disable_request_forgery_protection = true
+
+ # Raise error when a before_action's only/except options reference missing actions.
+ config.action_controller.raise_on_missing_callback_actions = true
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 6c9d48a..fd2d0e5 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,13 +1,10 @@
require "active_support/core_ext/integer/time"
Rails.application.configure do
- # Prepare the ingress controller used to receive mail
- # config.action_mailbox.ingress = :relay
-
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
- config.cache_classes = true
+ config.enable_reloading = false
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
@@ -16,55 +13,69 @@ Rails.application.configure do
config.eager_load = true
# Full error reports are disabled and caching is turned on.
- config.consider_all_requests_local = false
+ config.consider_all_requests_local = false
config.action_controller.perform_caching = true
- # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
- # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
+ # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment
+ # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
- # Disable serving static files from the `/public` folder by default since
- # Apache or NGINX already handles this.
- config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
+ # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
+ # config.public_file_server.enabled = false
# Compress CSS using a preprocessor.
# config.assets.css_compressor = :sass
- # Do not fallback to assets pipeline if a precompiled asset is missed.
+ # Do not fall back to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
- # config.asset_host = 'http://assets.example.com'
+ # config.asset_host = "http://assets.example.com"
# Specifies the header that your server uses for sending files.
- # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
- # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
+ # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local
# Mount Action Cable outside main process or domain.
# config.action_cable.mount_path = nil
- # config.action_cable.url = 'wss://example.com/cable'
- # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
+ # config.action_cable.url = "wss://example.com/cable"
+ # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
+
+ # Assume all access to the app is happening through a SSL-terminating reverse proxy.
+ # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
+ # config.assume_ssl = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
- # config.force_ssl = true
+ config.force_ssl = true
- # Include generic and useful information about system operation, but avoid logging too much
- # information to avoid inadvertent exposure of personally identifiable information (PII).
- config.log_level = :info
+ # Skip http-to-https redirect for the default health check endpoint.
+ # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
+
+ # Log to STDOUT by default
+ config.logger = ActiveSupport::Logger.new(STDOUT)
+ .tap { |logger| logger.formatter = ::Logger::Formatter.new }
+ .then { |logger| ActiveSupport::TaggedLogging.new(logger) }
# Prepend all log lines with the following tags.
config.log_tags = [ :request_id ]
+ # "info" includes generic and useful information about system operation, but avoids logging too much
+ # information to avoid inadvertent exposure of personally identifiable information (PII). If you
+ # want to log everything, set the level to "debug".
+ config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
+
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment).
- # config.active_job.queue_adapter = :resque
- # config.active_job.queue_name_prefix = "debshots_#{Rails.env}"
+ # config.active_job.queue_adapter = :resque
+ # config.active_job.queue_name_prefix = "debshots_production"
+ # Disable caching for Action Mailer templates even if Action Controller
+ # caching is enabled.
config.action_mailer.perform_caching = false
config.action_mailer.smtp_settings = {
@@ -86,32 +97,12 @@ Rails.application.configure do
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
- # Send deprecation notices to registered listeners.
- config.active_support.deprecation = :notify
-
- # Log disallowed deprecations.
- config.active_support.disallowed_deprecation = :log
-
- # Tell Active Support which deprecation messages to disallow.
- config.active_support.disallowed_deprecation_warnings = []
-
- # Use default logging formatter so that PID and timestamp are not suppressed.
- config.log_formatter = ::Logger::Formatter.new
-
- # Use a different logger for distributed setups.
- # require 'syslog/logger'
- # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
-
- if ENV["RAILS_LOG_TO_STDOUT"].present?
- logger = ActiveSupport::Logger.new(STDOUT)
- logger.formatter = config.log_formatter
- config.logger = ActiveSupport::TaggedLogging.new(logger)
- end
+ # Don't log any deprecations.
+ config.active_support.report_deprecations = false
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
- config.package_sources = [
{
description: 'Debian Unstable (Sid)', type: 'apt', url: 'http://ftp.de.debian.org/debian/dists/sid',
architectures: ['i386' ,'amd64']
@@ -129,7 +120,16 @@ Rails.application.configure do
# Any action dealing with authentication should redirect to HTTPS
# Disabled because it will redirect incorrectly behind a proxy.
# config.to_prepare { Devise::SessionsController.force_ssl }
-
+ # Only use :id for inspections in production.
# Needed (at least) for devise.rb to determine the oauth2 callback URL
config.base_url = ENV['DEBSHOTS_BASE_URL'] || 'http://localhost:3000'
+ config.active_record.attributes_for_inspect = [ :id ]
+
+ # Enable DNS rebinding protection and other `Host` header attacks.
+ # config.hosts = [
+ # "example.com", # Allow requests from example.com
+ # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
+ # ]
+ # Skip DNS rebinding protection for the default health check endpoint.
+ # config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 2f2ee06..9b22182 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -8,27 +8,25 @@ require "active_support/core_ext/integer/time"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
- config.cache_classes = false
- config.action_view.cache_template_loading = true
+ # While tests run files are not watched, reloading is not necessary.
+ config.enable_reloading = false
- # Do not eager load code on boot. This avoids loading your whole application
- # just for the purpose of running a single test. If you are using a tool that
- # preloads Rails for running tests, you may have to set it to true.
- config.eager_load = false
+ # Eager loading loads your entire application. When running a single test locally,
+ # this is usually not necessary, and can slow down your test suite. However, it's
+ # recommended that you enable it in continuous integration systems to ensure eager
+ # loading is working properly before deploying your code.
+ config.eager_load = ENV["CI"].present?
# Configure public file server for tests with Cache-Control for performance.
- config.public_file_server.enabled = true
- config.public_file_server.headers = {
- 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
- }
+ config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{1.hour.to_i}" }
# Show full error reports and disable caching.
- config.consider_all_requests_local = true
+ config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.cache_store = :null_store
- # Raise exceptions instead of rendering exception templates.
- config.action_dispatch.show_exceptions = false
+ # Render exception templates for rescuable exceptions and raise for other exceptions.
+ config.action_dispatch.show_exceptions = :rescuable
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
@@ -36,6 +34,8 @@ Rails.application.configure do
# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test
+ # Disable caching for Action Mailer templates even if Action Controller
+ # caching is enabled.
config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
@@ -43,6 +43,10 @@ Rails.application.configure do
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
+ # Unlike controllers, the mailer instance doesn't have any context about the
+ # incoming request so you'll need to provide the :host parameter yourself.
+ config.action_mailer.default_url_options = { host: "www.example.com" }
+
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
@@ -73,10 +77,5 @@ Rails.application.configure do
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
- # Needed (at least) for devise.rb to determine the oauth2 callback URL
config.base_url = ENV['DEBSHOTS_BASE_URL'] || 'http://localhost:3000'
end
-
-# Set base URL to be used in links in mails
-# https://github.com/rails/rails/issues/29992
-Rails.application.default_url_options = { host: 'localhost', port: 3000 }
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 2eeef96..bd5bcd2 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -9,4 +9,4 @@ Rails.application.config.assets.version = "1.0"
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
-# Rails.application.config.assets.precompile += %w( admin.js admin.css )
+# Rails.application.config.assets.precompile += %w[ admin.js admin.css ]
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index 54f47cf..b3076b3 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -16,9 +16,9 @@
# # policy.report_uri "/csp-violation-report-endpoint"
# end
#
-# # Generate session nonces for permitted importmap and inline scripts
+# # Generate session nonces for permitted importmap, inline scripts, and inline styles.
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
-# config.content_security_policy_nonce_directives = %w(script-src)
+# config.content_security_policy_nonce_directives = %w(script-src style-src)
#
# # Report violations without enforcing the policy.
# # config.content_security_policy_report_only = true
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
index adc6568..c010b83 100644
--- a/config/initializers/filter_parameter_logging.rb
+++ b/config/initializers/filter_parameter_logging.rb
@@ -1,8 +1,8 @@
# Be sure to restart your server when you modify this file.
-# Configure parameters to be filtered from the log file. Use this to limit dissemination of
-# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
-# notations and behaviors.
+# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
+# Use this to limit dissemination of sensitive information.
+# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [
- :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
+ :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
]
diff --git a/config/initializers/new_framework_defaults_7_2.rb b/config/initializers/new_framework_defaults_7_2.rb
new file mode 100644
index 0000000..b549c4a
--- /dev/null
+++ b/config/initializers/new_framework_defaults_7_2.rb
@@ -0,0 +1,70 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file eases your Rails 7.2 framework defaults upgrade.
+#
+# Uncomment each configuration one by one to switch to the new default.
+# Once your application is ready to run with all new defaults, you can remove
+# this file and set the `config.load_defaults` to `7.2`.
+#
+# Read the Guide for Upgrading Ruby on Rails for more info on each option.
+# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
+
+###
+# Controls whether Active Job's `#perform_later` and similar methods automatically defer
+# the job queuing to after the current Active Record transaction is committed.
+#
+# Example:
+# Topic.transaction do
+# topic = Topic.create(...)
+# NewTopicNotificationJob.perform_later(topic)
+# end
+#
+# In this example, if the configuration is set to `:never`, the job will
+# be enqueued immediately, even though the `Topic` hasn't been committed yet.
+# Because of this, if the job is picked up almost immediately, or if the
+# transaction doesn't succeed for some reason, the job will fail to find this
+# topic in the database.
+#
+# If `enqueue_after_transaction_commit` is set to `:default`, the queue adapter
+# will define the behaviour.
+#
+# Note: Active Job backends can disable this feature. This is generally done by
+# backends that use the same database as Active Record as a queue, hence they
+# don't need this feature.
+#++
+# Rails.application.config.active_job.enqueue_after_transaction_commit = :default
+
+###
+# Adds image/webp to the list of content types Active Storage considers as an image
+# Prevents automatic conversion to a fallback PNG, and assumes clients support WebP, as they support gif, jpeg, and png.
+# This is possible due to broad browser support for WebP, but older browsers and email clients may still not support
+# WebP. Requires imagemagick/libvips built with WebP support.
+#++
+# Rails.application.config.active_storage.web_image_content_types = %w[image/png image/jpeg image/gif image/webp]
+
+###
+# Enable validation of migration timestamps. When set, an ActiveRecord::InvalidMigrationTimestampError
+# will be raised if the timestamp prefix for a migration is more than a day ahead of the timestamp
+# associated with the current time. This is done to prevent forward-dating of migration files, which can
+# impact migration generation and other migration commands.
+#
+# Applications with existing timestamped migrations that do not adhere to the
+# expected format can disable validation by setting this config to `false`.
+#++
+# Rails.application.config.active_record.validate_migration_timestamps = true
+
+###
+# Controls whether the PostgresqlAdapter should decode dates automatically with manual queries.
+#
+# Example:
+# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.select_value("select '2024-01-01'::date") #=> Date
+#
+# This query used to return a `String`.
+#++
+# Rails.application.config.active_record.postgresql_adapter_decode_dates = true
+
+###
+# Enables YJIT as of Ruby 3.3, to bring sizeable performance improvements. If you are
+# deploying to a memory constrained environment you may want to set this to `false`.
+#++
+# Rails.application.config.yjit = true
diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb
index 00f64d7..7db3b95 100644
--- a/config/initializers/permissions_policy.rb
+++ b/config/initializers/permissions_policy.rb
@@ -1,11 +1,13 @@
+# Be sure to restart your server when you modify this file.
+
# Define an application-wide HTTP permissions policy. For further
-# information see https://developers.google.com/web/updates/2018/06/feature-policy
-#
-# Rails.application.config.permissions_policy do |f|
-# f.camera :none
-# f.gyroscope :none
-# f.microphone :none
-# f.usb :none
-# f.fullscreen :self
-# f.payment :self, "https://secure.example.com"
+# information see: https://developers.google.com/web/updates/2018/06/feature-policy
+
+# Rails.application.config.permissions_policy do |policy|
+# policy.camera :none
+# policy.gyroscope :none
+# policy.microphone :none
+# policy.usb :none
+# policy.fullscreen :self
+# policy.payment :self, "https://secure.example.com"
# end
diff --git a/config/puma.rb b/config/puma.rb
index d9b3e83..03c166f 100644
--- a/config/puma.rb
+++ b/config/puma.rb
@@ -1,43 +1,34 @@
-# Puma can serve each request in a thread from an internal thread pool.
-# The `threads` method setting takes two numbers: a minimum and maximum.
-# Any libraries that use thread pools should be configured to match
-# the maximum value specified for Puma. Default is set to 5 threads for minimum
-# and maximum; this matches the default thread size of Active Record.
-#
-max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
-min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
-threads min_threads_count, max_threads_count
+# This configuration file will be evaluated by Puma. The top-level methods that
+# are invoked here are part of Puma's configuration DSL. For more information
+# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html.
-# Specifies the `worker_timeout` threshold that Puma will use to wait before
-# terminating a worker in development environments.
+# Puma starts a configurable number of processes (workers) and each process
+# serves each request in a thread from an internal thread pool.
#
-worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
+# The ideal number of threads per worker depends both on how much time the
+# application spends waiting for IO operations and on how much you wish to
+# to prioritize throughput over latency.
+#
+# As a rule of thumb, increasing the number of threads will increase how much
+# traffic a given process can handle (throughput), but due to CRuby's
+# Global VM Lock (GVL) it has diminishing returns and will degrade the
+# response time (latency) of the application.
+#
+# The default is set to 3 threads as it's deemed a decent compromise between
+# throughput and latency for the average Rails application.
+#
+# Any libraries that use a connection pool or another resource pool should
+# be configured to provide at least as many connections as the number of
+# threads. This includes Active Record's `pool` parameter in `database.yml`.
+threads_count = ENV.fetch("RAILS_MAX_THREADS", 3)
+threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
-#
-port ENV.fetch("PORT") { 3000 }
+port ENV.fetch("PORT", 3000)
-# Specifies the `environment` that Puma will run in.
-#
-environment ENV.fetch("RAILS_ENV") { "development" }
-
-# Specifies the `pidfile` that Puma will use.
-pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
-
-# Specifies the number of `workers` to boot in clustered mode.
-# Workers are forked web server processes. If using threads and workers together
-# the concurrency of the application would be max `threads` * `workers`.
-# Workers do not work on JRuby or Windows (both of which do not support
-# processes).
-#
-# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
-
-# Use the `preload_app!` method when specifying a `workers` number.
-# This directive tells Puma to first boot the application and load code
-# before forking the application. This takes advantage of Copy On Write
-# process behavior so workers use less memory.
-#
-# preload_app!
-
-# Allow puma to be restarted by `rails restart` command.
+# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
+
+# Specify the PID file. Defaults to tmp/pids/server.pid in development.
+# In other environments, only set the PID file if requested.
+pidfile ENV["PIDFILE"] if ENV["PIDFILE"]
diff --git a/doc/README.Installation on Dokku.md b/doc/README.Installation on Dokku.md
new file mode 100644
index 0000000..ddf1976
--- /dev/null
+++ b/doc/README.Installation on Dokku.md
@@ -0,0 +1,212 @@
+# Installing debshots on Dokku
+
+## What is Dokku?
+
+[Dokku](https://dokku.com/) is an open-source software that helps deploy
+web applications. Once installed and set up you essentially do a _git push_ and
+Dokku will do its magic. It works similar to Heroku (a paid service) and
+even uses Heroku's _buildpacks_ for that purpose. It can handle common
+web frameworks like Ruby-on-Rails. It has been used for
+screenshots.debian.net in production for several years.
+
+Some of the features that make it a good choice:
+
+- healthchecks (will refuse to deploy if your new version is failing)
+- seamless deployment (no downtime while switching to the new version)
+- provides persistent volumes (where screenshots are stored)
+- provides a PostgreSQL database and tells the application how to access it
+ through an automatic environment variable
+- handles Let's Encrypt certificates automatically
+- deploying a new application version is done simply by _git push_
+
+## Install Dokku
+
+Grab a (virtual) server with at least 3 GB of RAM and 20 GB of SSD space.
+The application is currently run on a Hetzner server in Germany that costs
+less than 5€ per month.
+
+Follow the installation instructions on https://dokku.com/
+
+Install the _Let's Encrypt_ plugin:
+
+ dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
+
+Set the email address as a contact for Let's Encrypt:
+
+ dokku letsencrypt:set screenshots-beta.debian.net email haas@debian.org
+
+Create a new blank Dokku application:
+
+ dokku apps:create screenshots-beta.debian.net
+
+Create a new blank PostgreSQL database and link it to the application:
+
+ dokku postgres:create screenshots_beta
+ dokku postgres:link screenshots_beta screenshots-beta.debian.net
+
+Create a directory that will hold the screenshots' files:
+
+ mkdir -p /srv/www/screenshots-beta.debian.net/shrine
+
+Mount it into the application's path:
+
+ dokku storage:mount screenshots-beta.debian.net /srv/www/screenshots-beta.debian.net/shrine:/app/public/shrine
+
+By default the Nginx (that Dokku provides) will only allow uploads up to 1 MB.
+You may want to increase that limit:
+
+ dokku nginx:set screenshots-beta.debian.net client-max-body-size 10m
+ dokku proxy:build-config screenshots-beta.debian.net
+
+If you want to add a message that gets printed on all pages you can set
+an environment variable for that purpose:
+
+ dokku config:set screenshots-beta.debian.net DEBSHOTS\_ALERT\_MESSAGE='This is a staging site. Uploads will not persist. Testing only.'
+
+
+
+dokku config:set --no-restart screenshots-beta.debian.net SALSA_OAUTH_SECRET='c4c137fcbbcb5d9c6ff98a76bbf45bceee77ebe13645198359a0fa38cd8fb1d0'
+dokku config:set --no-restart screenshots-beta.debian.net SALSA_OAUTH_KEY='644440cd5595b3b7aea6e959ab1488e7026c2b5cf24faea8f9af5ce914377d52'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Make sure that you set the environment variables as described in README.SSO.md before
+you start the Rails application. Otherwise most single sign-on providers cannot work.
+You also need to get the https://salsa.debian.org/debsso-team/debsso/raw/master/update-debsso-ca
+script and run it in /etc/nginx to update the certficate and CRL used by the Debian
+single-sign-on provider.
+
+The production configuration uses Nginx that decrypts HTTPS and either serves static
+assets (images, Javascript, CSS) itself or requests for dynamic content to the
+Rails application. You will need a SSL certificate for Nginx. Just get one from
+LetsEncrypt using the *certbot* tool.
+
+Finally create an admin user for moderation:
+
+Start a Rails console:
+
+ rails c -e production
+
+Create a new user record:
+
+ user = User.create(realname: 'Christoph Haas', password: 'foobartest', email: 'email@christoph-haas.de')
+ user.save!
+
+## Cron jobs
+
+Parse Nginx access logs to count the number of visits of each package:
+
+ RAILS_ENV=production bundle exec rake debshots:accesslog2visits[/var/log/nginx/cache-access.log.1]
+
+As a cron job:
+
+ 41 9 * * * cd $HOME/debshots ; RAILS_ENV=production /home/debshots/.rbenv/shims/bundle exec rake debshots:accesslog2visits[/var/log/nginx/cache-access.log.1]
+
+Get the latest information on packages from the Debian repositories.
+
+ bundle exec rails debshots:update_from_deb_repos RAILS_ENV=production
+ bundle exec rails debshots:update_longdescription_from_deb_repos RAILS_ENV=production
+
+# Authentication
+
+This web application tries to avoid to create yet another directory
+of user accounts. So it leverages other common web sites like StackExchange,
+Debian SSO (using browser/client certificates) or GitHub as single-sign-on
+services. It is still possible to create local user accounts for administrators
+but registration is disabled.
+
+Anonymous uploads are possible but they have to be moderated by an administrator.
+
+# Authorization (not yet implemented)
+
+A user can have one of these access levels.
+
+## Anonymous
+
+Without authentication all user actions are moderated. Such users can upload
+screenshots or report existing/published screenshots as inappropriate. However
+a user with level 'admin' will have to approve that action.
+
+## Authenticated by single-sign-login (SSO)
+
+Users can use different authentication services to login - like Github or
+StackExchange. Such users internally get an account with a random password
+created but they will keep logging in via SSO.
+
+The first upload will have to be moderated. Subsequent uploads will be
+approved automatically.
+
+## Authenticated by Debian signle-sign-login (SSO)
+
+If a user authenticates using a Debian SSO client certificate they will be
+able to upload screenshots without moderation.
+(Anohter idea was to restrict them to uploading only screenshots for the
+packages they maintain. But that may be reliable and is not implemented at
+this time.)
+
+## Administrator
+
+Such a user has an internal user account. The database record has the
+'admin' field set to 1. Admins can freely upload, moderate and delete
+screenshots. They can also read the log files.
+
+# Nginx during development
+
+During development it is advised to run Nginx to proxy ports 3000 (HTTP)
+and 3001 (HTTPS) to the rails application.
+
+ cd nginx
+ nginx -c `pwd`/nginx.conf
+
+The SSL certitificate is just a self-signed certificate with the
+common name "localhost". It was generated using:
+
+ openssl req -x509 -newkey 4096 -nodes -keyout localhost.key -out localhost.crt -days 3650
+
+Run "rails s" in another window. That will use the built-in Ruby 'Puma'
+application server that can also be used in production. It requires less
+configuration than Phusion Passenger but may be slower in regard to
+performance and multi-threading / multi-core support.
+
+If you get "400 Bad Request / The SSL certificate error" in the browser then
+please check the error log (/tmp/error*). Once cause is that the CRL of
+the Debian SSO has expired and needs to be updated.
+
+# Tidy up the screenshot data:
+
+bundle exec rake debshots:remove_broken_screenshots
+
+bundle exec rake debshots:remove_duplicate_images
+
+# Frequent update of Debian SSO certificate
+
+Run /etc/nginx/update-sso-ca regularly to update the CA certificate and the CRL.
+The CRL (certificate revocation list) is only valid for three days. So make sure
+you have a daily cron job for the updates. Do not forget to restart Nginx afterwards.
+
+Otherwise you will end up with this error message:
+
+ 400 Bad Request
+ The SSL certificate error
+ nginx
diff --git a/doc/README.Installation.md b/doc/README.Installation.md
index 6c6e279..dfc8ce9 100644
--- a/doc/README.Installation.md
+++ b/doc/README.Installation.md
@@ -43,7 +43,7 @@ Start a Rails console:
Create a new user record:
- user = User.create(realname: 'Christoph Haas', password: 'foobartest', email: 'email@christoph-haas.de')
+ user = User.create(realname: 'Christoph Haas', password: 'foobartest', email: 'email@christoph-haas.de', provider: 'local')
user.save!
## Cron jobs
diff --git a/lib/deb_importer.rb b/lib/deb_importer.rb
index 06b355b..071db04 100644
--- a/lib/deb_importer.rb
+++ b/lib/deb_importer.rb
@@ -14,13 +14,12 @@ require 'pp'
# Next it loads the Packages lists (prefers bz2, falls back to
# .gz or even the uncompressed version).
module DebImporter
-
# Defines a Debian release
class Release
attr_reader :architectures, :components, :description, :codename, :origin, :version, :files
# Load and parse a Release file of an APT repository
- def initialize(dist_url) # rubocop:disable Metrics/MethodLength
+ def initialize(dist_url)
@dist_url = dist_url
release_url = "#{dist_url}/Release"
Rails.logger.debug "Loading Release file from #{release_url}"
@@ -42,11 +41,9 @@ module DebImporter
def i18n(component, language)
url = "#{@dist_url}/#{component}/i18n/Translation-#{language}"
file = find_and_open_compressed_url(url)
- if file
- return get_paragraphs(file)
- else
- return []
- end
+ return get_paragraphs(file) if file
+
+ []
end
# Look for the file or URL in various compressed formats
@@ -66,14 +63,14 @@ module DebImporter
file2 = nil
# Decompress file depending on its filename suffix
- case suffix
- when '.bz2'
- file2 = Bzip2::FFI::Reader.read(file)
- when '.gz'
- file2 = Zlib::GzipReader.new(file)
- else # plain text
- file2 = file
- end
+ file2 = case suffix
+ when '.bz2'
+ Bzip2::FFI::Reader.read(file)
+ when '.gz'
+ Zlib::GzipReader.new(file)
+ else # plain text
+ file
+ end
Rails.logger.debug "File containing translations is: #{url}"
# Return an enumerator that iterates over lines of the file
@@ -112,7 +109,7 @@ module DebImporter
when /^(\S+?):$/ # "Key:" (start of multi-line entry without value in line)
fields[name.to_sym] = value unless value.empty?
name = $1
- value = ""
+ value = ''
when /^\s(.+)/ # " Indented multi-line value"
# Add a newline for multi-line entries ("Key: Value\n Foo\n Bar")
value += "\n" unless value.empty?
@@ -138,7 +135,7 @@ module DebImporter
gathered_lines = [] # collects all lines belonging to a field
data.each_line do |line|
- #Rails.logger.debug("___" + line)
+ # Rails.logger.debug("___" + line)
if line.chomp.empty? # empty line found that seperates paragraphs
if gathered_lines.any? # any lines gathered so far?
# Rails.logger.debug('>>>>>>>>>>>>>>>>>>>>>> Gathered lines:')
@@ -156,7 +153,7 @@ module DebImporter
enum.yield get_fields(gathered_lines) if gathered_lines.any?
end
end
-
+
# Represents the version of a Debian package
class Version
attr_reader :epoch, :upstream, :revision, :version_string
@@ -165,10 +162,10 @@ module DebImporter
@version_string = version_string
# Split into "[epoch:]upstream[-revision]"
# See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#version
- unless /^((?\d+)\:)?(?.+?)(\-(?.+))?$/ =~ version_string
+ unless /^((?\d+):)?(?.+?)(-(?.+))?$/ =~ version_string
raise ArgumentError, "Cannot parse version string: #{version_string}"
end
-
+
@epoch = epoch || '0'
@upstream = upstream
@revision = revision if revision
diff --git a/public/406-unsupported-browser.html b/public/406-unsupported-browser.html
new file mode 100644
index 0000000..7cf1e16
--- /dev/null
+++ b/public/406-unsupported-browser.html
@@ -0,0 +1,66 @@
+
+
+
+ Your browser is not supported (406)
+
+
+
+
+
+
+
+
+
Your browser is not supported.
+
Please upgrade your browser to continue.
+
+
+
+
diff --git a/test/controllers/packages_controller_test.rb b/test/controllers/packages_controller_test.rb
index 873097a..9a9d9d5 100644
--- a/test/controllers/packages_controller_test.rb
+++ b/test/controllers/packages_controller_test.rb
@@ -8,6 +8,13 @@ class PackagesControllerTest < ActionController::TestCase
end
test "should get list view with_screenshots and find Firefox" do
+ # package = Package.create!(name: 'firefox', description: 'A web browser.')
+ # Screenshot.create!(package: package, approved: true, hidden: false)
+
+ # get :list, params: { show: 'with' }
+ # assert_response :success
+ # assert_select 'div', 'A web browser.'
+
get :list, params: { show: 'with' }
assert_response :success
assert_select 'div', 'A program to browse web sites.'