Update to Rails 7.2

This commit is contained in:
Christoph Haas 2025-02-25 21:57:16 +01:00
parent 932a43daac
commit 25672aabb0
31 changed files with 836 additions and 435 deletions

14
Gemfile
View file

@ -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"

View file

@ -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

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,4 @@
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
//= link application.js

View file

@ -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;

View file

@ -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

View file

@ -0,0 +1,4 @@
last 2 versions
ie >= 9
Android >= 2.3
ios >= 7

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= content_for?(:title) ? yield(:title) : "Untitled" %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>

View file

@ -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

View file

@ -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")

View file

@ -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")

View file

@ -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

View file

@ -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.
#

View file

@ -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

View file

@ -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

View file

@ -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 }

View file

@ -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 ]

View file

@ -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

View file

@ -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
]

View file

@ -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

View file

@ -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

View file

@ -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"]

View file

@ -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

View file

@ -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

View file

@ -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 /^((?<epoch>\d+)\:)?(?<upstream>.+?)(\-(?<revision>.+))?$/ =~ version_string
unless /^((?<epoch>\d+):)?(?<upstream>.+?)(-(?<revision>.+))?$/ =~ version_string
raise ArgumentError, "Cannot parse version string: #{version_string}"
end
@epoch = epoch || '0'
@upstream = upstream
@revision = revision if revision

View file

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>Your browser is not supported (406)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
.rails-default-error-page {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
.rails-default-error-page div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
.rails-default-error-page div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
.rails-default-error-page h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
.rails-default-error-page div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body class="rails-default-error-page">
<!-- This file lives in public/406-unsupported-browser.html -->
<div class="dialog">
<div>
<h1>Your browser is not supported.</h1>
<p>Please upgrade your browser to continue.</p>
</div>
</div>
</body>
</html>

View file

@ -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.'