summaryrefslogtreecommitdiff
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/application.rb1
-rw-r--r--config/environments/test.rb2
-rw-r--r--config/initializers/content_security_policy.rb49
-rw-r--r--config/initializers/ensure_search_vector_trigger.rb7
-rw-r--r--config/initializers/error_log.rb20
-rw-r--r--config/initializers/rails_icons.rb16
-rw-r--r--config/locales/de.yml118
-rw-r--r--config/locales/en.yml56
-rw-r--r--config/routes.rb90
9 files changed, 248 insertions, 111 deletions
diff --git a/config/application.rb b/config/application.rb
index 0be3396..5ec3e8f 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -17,6 +17,7 @@ module Cccms
17 config.time_zone = 'Berlin' 17 config.time_zone = 'Berlin'
18 18
19 config.i18n.default_locale = :de 19 config.i18n.default_locale = :de
20 config.i18n.available_locales = [:de, :en]
20 config.i18n.fallbacks = { en: [:en, :de] } 21 config.i18n.fallbacks = { en: [:en, :de] }
21 22
22 config.filter_parameters += [:password, :password_confirmation] 23 config.filter_parameters += [:password, :password_confirmation]
diff --git a/config/environments/test.rb b/config/environments/test.rb
index bb89065..08fcefa 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -42,6 +42,8 @@ Rails.application.configure do
42 # Print deprecation notices to the stderr. 42 # Print deprecation notices to the stderr.
43 config.active_support.deprecation = :stderr 43 config.active_support.deprecation = :stderr
44 44
45 config.active_record.verify_foreign_keys_for_fixtures = false
46
45 # Raises error for missing translations. 47 # Raises error for missing translations.
46 # config.i18n.raise_on_missing_translations = true 48 # config.i18n.raise_on_missing_translations = true
47 49
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index d51d713..1569942 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -4,26 +4,29 @@
4# See the Securing Rails Applications Guide for more information: 4# See the Securing Rails Applications Guide for more information:
5# https://guides.rubyonrails.org/security.html#content-security-policy-header 5# https://guides.rubyonrails.org/security.html#content-security-policy-header
6 6
7# Rails.application.configure do 7Rails.application.configure do
8# config.content_security_policy do |policy| 8 config.content_security_policy do |policy|
9# policy.default_src :self, :https 9 policy.default_src :self
10# policy.font_src :self, :https, :data 10 policy.script_src :self
11# policy.img_src :self, :https, :data 11 policy.style_src :self, :unsafe_inline
12# policy.object_src :none 12 policy.img_src :self, :data
13# policy.script_src :self, :https 13 policy.font_src :self
14# policy.style_src :self, :https 14 policy.object_src :none
15# # Specify URI for violation reports 15 policy.frame_ancestors :none
16# # policy.report_uri "/csp-violation-report-endpoint" 16 policy.base_uri :self
17# end 17 policy.form_action :self
18# 18 policy.report_uri "/csp_reports"
19# # Generate session nonces for permitted importmap, inline scripts, and inline styles. 19 end
20# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 20
21# config.content_security_policy_nonce_directives = %w(script-src style-src) 21 # Per-request nonce; script-src only. style-src keeps unsafe_inline
22# 22 # deliberately: TinyMCE emits img[style] in body content and the
23# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag` 23 # public layout carries style attributes -- CSS injection is a
24# # if the corresponding directives are specified in `content_security_policy_nonce_directives`. 24 # low-yield channel, script-src is where the protection lives.
25# # config.content_security_policy_nonce_auto = true 25 config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
26# 26 config.content_security_policy_nonce_directives = %w[script-src]
27# # Report violations without enforcing the policy. 27
28# # config.content_security_policy_report_only = true 28 # Report-only: nothing blocks. Enforcement is a later, deliberate
29# end 29 # flip once the reports have mapped reality (admin inline scripts,
30 # legacy hotlinked images in old bodies, embeds).
31 config.content_security_policy_report_only = true
32end
diff --git a/config/initializers/ensure_search_vector_trigger.rb b/config/initializers/ensure_search_vector_trigger.rb
new file mode 100644
index 0000000..a750e9c
--- /dev/null
+++ b/config/initializers/ensure_search_vector_trigger.rb
@@ -0,0 +1,7 @@
1Rails.application.config.after_initialize do
2 begin
3 Page.ensure_search_vector_trigger! if Page.connection.table_exists?(:page_translations)
4 rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad
5 # Database doesn't exist yet -- e.g. mid `rails db:create`. Nothing to install yet.
6 end
7end
diff --git a/config/initializers/error_log.rb b/config/initializers/error_log.rb
new file mode 100644
index 0000000..74117cb
--- /dev/null
+++ b/config/initializers/error_log.rb
@@ -0,0 +1,20 @@
1# Every controller-level exception (the 500s) in one lean file,
2# independent of the base log level -- log/production.log can stay
3# quiet without losing error visibility.
4if Rails.env.production?
5 error_logger = ActiveSupport::Logger.new(Rails.root.join("log", "errors.log"))
6
7 ActiveSupport::Notifications.subscribe("process_action.action_controller") do |*, payload|
8 if (exception = payload[:exception_object])
9 status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception.class.name)
10 next if status < 500
11
12 error_logger.error(
13 "#{Time.now.iso8601} [#{status}] #{payload[:controller]}##{payload[:action]} #{payload[:path]} " \
14 "-- #{exception.class}: #{exception.message}\n " +
15 Array(exception.backtrace).first(5).join("\n ")
16 )
17 end
18 end
19end
20
diff --git a/config/initializers/rails_icons.rb b/config/initializers/rails_icons.rb
new file mode 100644
index 0000000..1503db7
--- /dev/null
+++ b/config/initializers/rails_icons.rb
@@ -0,0 +1,16 @@
1RailsIcons.configure do |config|
2 config.default_library = "tabler"
3 config.default_variant = "outline" # Set a default variant for all libraries
4
5 # Override Tabler defaults
6 # config.libraries.tabler.default_variant = "" # Set a default variant for Tabler
7 # config.libraries.tabler.exclude_variants = [] # Exclude specific variants
8
9 # config.libraries.tabler.regular.default.css = "size-6"
10 # config.libraries.tabler.solid.default.css = "size-6"
11 # config.libraries.tabler.solid.default.data = {}
12
13 # config.libraries.tabler.outline.default.css = "size-6"
14 # config.libraries.tabler.outline.default.stroke_width = "2"
15 # config.libraries.tabler.outline.default.data = {}
16end
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 5f77d79..f64f6cd 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -7,6 +7,19 @@ de:
7 sponsors: Sponsoren 7 sponsors: Sponsoren
8 show_tag_headline: "Seiten mit dem Tag:" 8 show_tag_headline: "Seiten mit dem Tag:"
9 old_ccc_de: das alte ccc.de 9 old_ccc_de: das alte ccc.de
10 event_schedule_time: "um %{time} Uhr"
11 event_schedule_unrecognized: "Termin-Regel nicht automatisch lesbar"
12 event_schedule_none: "Kein Termin"
13 open_days: "Offene Tage"
14 open_days_label: "Offene Tage"
15 upcoming_events: "Weitere Termine"
16 open_today: "Das Chaos, lokal und heute offen"
17 published: "veröffentlicht"
18 published_by: "veröffentlicht durch %{editor}"
19 last_edited: "zuletzt bearbeitet"
20 last_edited_by: "zuletzt bearbeitet durch %{editor}"
21 editor_self: "du"
22 publisher_self: "dich"
10 date: 23 date:
11 formats: 24 formats:
12 default: "%d.%m.%Y" 25 default: "%d.%m.%Y"
@@ -22,7 +35,6 @@ de:
22 - :day 35 - :day
23 - :month 36 - :month
24 - :year 37 - :year
25
26 time: 38 time:
27 formats: 39 formats:
28 default: "%A, %e. %B %Y, %H:%M Uhr" 40 default: "%A, %e. %B %Y, %H:%M Uhr"
@@ -34,42 +46,6 @@ de:
34 am: "vormittags" 46 am: "vormittags"
35 pm: "nachmittags" 47 pm: "nachmittags"
36 48
37 datetime:
38 distance_in_words:
39 half_a_minute: 'eine halbe Minute'
40 less_than_x_seconds:
41 zero: 'weniger als 1 Sekunde'
42 one: 'weniger als 1 Sekunde'
43 other: 'weniger als {{count}} Sekunden'
44 x_seconds:
45 one: '1 Sekunde'
46 other: '{{count}} Sekunden'
47 less_than_x_minutes:
48 zero: 'weniger als 1 Minute'
49 one: 'weniger als eine Minute'
50 other: 'weniger als {{count}} Minuten'
51 x_minutes:
52 one: '1 Minute'
53 other: '{{count}} Minuten'
54 about_x_hours:
55 one: 'etwa 1 Stunde'
56 other: 'etwa {{count}} Stunden'
57 x_days:
58 one: '1 Tag'
59 other: '{{count}} Tage'
60 about_x_months:
61 one: 'etwa 1 Monat'
62 other: 'etwa {{count}} Monate'
63 x_months:
64 one: '1 Monat'
65 other: '{{count}} Monate'
66 about_x_years:
67 one: 'etwa 1 Jahr'
68 other: 'etwa {{count}} Jahre'
69 over_x_years:
70 one: 'mehr als 1 Jahr'
71 other: 'mehr als {{count}} Jahre'
72
73 number: 49 number:
74 format: 50 format:
75 precision: 2 51 precision: 2
@@ -98,31 +74,45 @@ de:
98 sentence_connector: "und" 74 sentence_connector: "und"
99 skip_last_comma: true 75 skip_last_comma: true
100 76
101 activerecord: 77 will_paginate:
102 errors: 78 previous_label: "&#8592; Zurück"
103 template: 79 previous_aria_label: "Vorherige Seite"
104 header: 80 next_label: "Weiter &#8594;"
105 one: 1 error prohibited this {{model}} from being saved 81 next_aria_label: "Nächste Seite"
106 other: "{{count}} errors prohibited this {{model}} from being saved" 82 page_gap: "&hellip;"
107 body: "There were problems with the following fields:" 83 container_aria_label: "Seitennavigation"
84 page_aria_label: "Seite %{page}"
108 85
109 messages: 86 node_actions:
110 inclusion: "is not included in the list" 87 heading: "Letzte Änderungen"
111 exclusion: "is reserved" 88 show_all: "Alle Einträge zeigen"
112 invalid: "is invalid" 89 backfilled: "rekonstruiert"
113 confirmation: "doesn't match confirmation" 90 show_changes: "Änderungen an Übersetzungen"
114 accepted: "must be accepted" 91 view_revision: "Diese Revision ansehen"
115 empty: "can't be empty" 92 unknown: "%{actor} hat %{action} auf %{subject} ausgeführt"
116 blank: "can't be blank" 93 publish: "%{actor} hat %{revision} von %{subject} veröffentlicht"
117 too_long: "is too long (maximum is {{count}} characters)" 94 publish_rollback: "%{actor} hat %{subject} auf %{revision} zurückgesetzt"
118 too_short: "is too short (minimum is {{count}} characters)" 95 publish_first: "%{actor} hat %{subject} zum ersten Mal veröffentlicht"
119 wrong_length: "is the wrong length (should be {{count}} characters)" 96 publish_first_with_author: "%{actor} hat %{subject} zum ersten Mal veröffentlicht (Autor: %{author})"
120 taken: "has already been taken" 97 create: "%{actor} hat %{subject} unter %{path} angelegt"
121 not_a_number: "is not a number" 98 move: "%{actor} hat %{subject} von %{from} nach %{to} verschoben"
122 greater_than: "must be greater than {{count}}" 99 discard_autosave: "%{actor} hat ungespeicherte Änderungen an %{subject} verworfen"
123 greater_than_or_equal_to: "must be greater than or equal to {{count}}" 100 destroy_draft: "%{actor} hat den Entwurf von %{subject} verworfen"
124 equal_to: "must be equal to {{count}}" 101 locale_added: "Übersetzung angelegt, Titel \"%{title}\""
125 less_than: "must be less than {{count}}" 102 locale_removed: "Übersetzung entfernt, letzter Titel \"%{title}\""
126 less_than_or_equal_to: "must be less than or equal to {{count}}" 103 abstract_changed: "Abstract geändert"
127 odd: "must be odd" 104 body_changed: "Text geändert"
128 even: "must be even" 105 revision_new: "eine neue Revision"
106 revision_earlier: "eine frühere Revision"
107 node_history: "Chronik"
108 detail_title: "Titel „%{from}“ → „%{to}“"
109 detail_author: "Autor %{from} → %{to}"
110 detail_tags: "Tags %{from} → %{to}"
111 template_changed: "Template geändert"
112 assets_changed: "Bildliste geändert"
113 trash: "%{actor} hat %{subject} in den Papierkorb verschoben (vorher unter %{from})"
114 restore_from_trash: "%{actor} hat %{subject} aus dem Papierkorb nach %{to} wiederhergestellt"
115 destroy: "%{actor} hat %{subject} endgültig gelöscht (zuletzt unter %{path})"
116 revision_created: "angelegt am %{date} von %{actor}"
117 revision_published: "veröffentlicht am %{date} von %{actor}"
118 revision_restored: "wiederhergestellt am %{date} von %{actor}"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 2458d4d..8a8acc1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -8,7 +8,63 @@ en:
8 hello: "Hello world" 8 hello: "Hello world"
9 show_tag_headline: "Pages tagged with:" 9 show_tag_headline: "Pages tagged with:"
10 old_ccc_de: the old ccc.de 10 old_ccc_de: the old ccc.de
11 event_schedule_time: "at %{time}"
12 event_schedule_unrecognized: "Schedule not automatically readable"
13 event_schedule_none: "No schedule"
14 open_days: "Open days"
15 open_days_label: "Open days"
16 upcoming_events: "Upcoming events"
17 open_today: "Open today"
18 published: "published"
19 published_by: "published by %{editor}"
20 last_edited: "last edited"
21 last_edited_by: "last edited by %{editor}"
22 publisher_self: "you"
23 editor_self: "you"
11 24
12 time: 25 time:
13 formats: 26 formats:
14 ccc: "%d %B, %Y %H:%M" 27 ccc: "%d %B, %Y %H:%M"
28
29 will_paginate:
30 previous_label: "&#8592; Previous"
31 previous_aria_label: "Previous page"
32 next_label: "Next &#8594;"
33 next_aria_label: "Next page"
34 page_gap: "&hellip;"
35 container_aria_label: "Pagination"
36 page_aria_label: "Page %{page}"
37
38 node_actions:
39 heading: "Action log"
40 show_all: "Show all entries"
41 backfilled: "backfilled"
42 show_changes: "translation changes"
43 view_revision: "view this revision"
44 unknown: "%{actor} did %{action} on %{subject}"
45 publish: "%{actor} published %{revision} of %{subject}"
46 publish_rollback: "%{actor} rolled %{subject} back to %{revision}"
47 publish_first: "%{actor} published %{subject} for the first time"
48 publish_first_with_author: "%{actor} published %{subject} for the first time (author: %{author})"
49 create: "%{actor} created %{subject} at %{path}"
50 move: "%{actor} moved %{subject} from %{from} to %{to}"
51 discard_autosave: "%{actor} discarded unsaved changes on %{subject}"
52 destroy_draft: "%{actor} discarded the draft of %{subject}"
53 locale_added: "translation added, titled \"%{title}\""
54 locale_removed: "translation removed, last titled \"%{title}\""
55 abstract_changed: "abstract changed"
56 body_changed: "body changed"
57 revision_new: "a new revision"
58 revision_earlier: "an earlier revision"
59 node_history: "node history"
60 detail_title: "title \"%{from}\" → \"%{to}\""
61 detail_author: "author %{from} → %{to}"
62 detail_tags: "tags %{from} → %{to}"
63 template_changed: "template changed"
64 assets_changed: "attached images changed"
65 trash: "%{actor} moved %{subject} to the Trash (was at %{from})"
66 restore_from_trash: "%{actor} restored %{subject} from the Trash to %{to}"
67 destroy: "%{actor} permanently deleted %{subject} (last at %{path})"
68 revision_created: "created %{date} by %{actor}"
69 revision_published: "published %{date} by %{actor}"
70 revision_restored: "restored %{date} by %{actor}"
diff --git a/config/routes.rb b/config/routes.rb
index a7775b3..6ddf48c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -9,6 +9,8 @@ Cccms::Application.routes.draw do
9 defaults: { page_path: ['home'] }, 9 defaults: { page_path: ['home'] },
10 constraints: { locale: /de|en/ } 10 constraints: { locale: /de|en/ }
11 11
12 post 'csp_reports' => 'csp_reports#create'
13
12 # All application routes are scoped under an optional two-letter locale 14 # All application routes are scoped under an optional two-letter locale
13 # prefix: /de/... and /en/... Both forms are valid; the prefix is omitted 15 # prefix: /de/... and /en/... Both forms are valid; the prefix is omitted
14 # for the default locale (:de) in generated URLs via default_url_options 16 # for the default locale (:de) in generated URLs via default_url_options
@@ -20,41 +22,81 @@ Cccms::Application.routes.draw do
20 scope '(:locale)', locale: /de|en/ do 22 scope '(:locale)', locale: /de|en/ do
21 23
22 resources :tags 24 resources :tags
23 resources :occurrences
24 resources :events
25 25
26 resources :pages do 26 resources :events do
27 member do 27 collection do
28 get :preview 28 get :without_node
29 put :sort_images
30 end 29 end
31 end 30 end
32 31
33 resources :nodes do 32 get 'pages/:id/preview', to: 'pages#preview', as: :preview_page
34 member do 33 put 'pages/:id/sort_images', to: 'pages#sort_images', as: :sort_images_page
35 put :unlock 34
36 put :publish 35 get 'preview/:token', to: 'shared_previews#show', as: :shared_preview
37 end
38 36
39 resources :revisions do 37 scope '/admin' do
38 resources :assets
39
40 resources :nodes do
40 collection do 41 collection do
41 post :diff 42 get 'tags/:tags', action: :tags, as: :tags, constraints: { tags: /[^\/]+/ }
43 get :parameterize_preview
44 get :drafts
45 get :recent
46 get :mine
47 get :chapters
48 get :sitemap
49 get :trashed
42 end 50 end
51
43 member do 52 member do
44 put :restore 53 put :unlock
54 put :publish
55 put :generate_shared_preview
56 put :revoke_shared_preview
57 put :autosave
58 put :revert
59 put :trash
60 put :restore_from_trash
61 end
62
63 resources :translations, controller: 'page_translations',
64 param: :translation_locale,
65 constraints: { translation_locale: /en/ },
66 only: [:show, :edit, :update, :destroy] do
67 member do
68 put :autosave
69 end
70 end
71
72 resources :related_assets, only: [:create, :destroy, :update] do
73 collection do
74 get :search
75 end
76 end
77
78 resources :revisions do
79 collection do
80 post :diff
81 get :diff
82 end
83 member do
84 put :restore
85 end
45 end 86 end
46 end 87 end
47 end
48 88
49 scope '/admin' do 89 match '' => 'admin#index', :as => :admin, :via => :get
50 resources :assets 90 match 'search' => 'admin#search', :as => :admin_search, :via => :get
91 match 'menu_search' => 'admin#menu_search', :as => :admin_menu_search, :via => :get
92 match 'conventions' => 'admin#conventions', :as => :admin_conventions, :via => :get
93 match 'dashboard_search' => 'admin#dashboard_search', :as => :admin_dashboard_search, :via => :get
94 match 'log' => 'node_actions#index', :as => :admin_log, :via => :get
95 match 'boom' => 'admin#boom', :as => :admin_boom, :via => :get
51 end 96 end
52 97
53 match '/logout' => 'sessions#destroy', :as => :logout, :via => :delete 98 match '/logout' => 'sessions#destroy', :as => :logout, :via => :delete
54 match '/login' => 'sessions#new', :as => :login, :via => :get 99 match '/login' => 'sessions#new', :as => :login, :via => :get
55 match 'admin' => 'admin#index', :as => :admin, :via => :get
56 match 'admin/search' => 'admin#search', :as => :admin_search, :via => :get
57 match 'admin/menu_search' => 'admin#menu_search', :as => :admin_menu_search, :via => :get
58 match 'search' => 'search#index', :as => :search, :via => :get 100 match 'search' => 'search#index', :as => :search, :via => :get
59 101
60 resources :users 102 resources :users
@@ -67,11 +109,11 @@ Cccms::Application.routes.draw do
67 109
68 resource :session 110 resource :session
69 111
70 get 'rss/updates', :to => 'rss#updates', :as => :rss 112 get 'rss/updates', :to => 'rss#updates', :as => :rss, :defaults => { :format => :xml }
71 get 'rss/updates.:format', :to => 'rss#updates', :as => :rss_feed, 113 get 'rss/updates.:format', :to => 'rss#updates', :as => :rss_feed, :defaults => { :format => :xml },
72 :constraints => { :format => /xml|rdf/ } 114 :constraints => { :format => /xml|rdf/ }
73 get 'rss/tags/:tag/updates', :to => 'rss#tag_updates', :as => :rss_tag 115 get 'rss/tags/:tag/updates', :to => 'rss#tag_updates', :as => :rss_tag, :defaults => { :format => :xml }
74 get 'rss/tags/:tag/updates.:format', :to => 'rss#tag_updates', :as => :rss_tag_feed, 116 get 'rss/tags/:tag/updates.:format', :to => 'rss#tag_updates', :as => :rss_tag_feed, :defaults => { :format => :xml },
75 :constraints => { :format => /xml/ } 117 :constraints => { :format => /xml/ }
76 118
77 match 'galleries/*page_path' => 'content#render_gallery', :via => :get 119 match 'galleries/*page_path' => 'content#render_gallery', :via => :get