├── .browserslistrc ├── .circleci └── config.yml ├── .codebeatignore ├── .codeclimate.yml ├── .env.development ├── .env.test ├── .flayignore ├── .github └── dependabot.yml ├── .gitignore ├── .overcommit.yml ├── .pryrc ├── .rspec ├── .rspec_parallel ├── .rubocop.yml ├── .ruby-version ├── .rubycritic.yml ├── .scss-lint.yml ├── .typo-ci.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── Procfile ├── README.md ├── Rakefile ├── app ├── assets │ └── config │ │ └── manifest.js ├── controllers │ ├── application_controller.rb │ └── blazer │ │ └── application_controller.rb ├── models │ ├── ahoy │ │ ├── event.rb │ │ ├── message.rb │ │ └── visit.rb │ └── application_record.rb ├── policies │ └── ahoy │ │ ├── message_policy.rb │ │ └── visit_policy.rb └── validators │ ├── mjml_syntax_validator.rb │ └── unique_in_collection_validator.rb ├── babel.config.js ├── bin ├── brakeman ├── bundle ├── dev ├── packwerk ├── rails ├── rake ├── rspec ├── rubocop └── setup ├── config.ru ├── config ├── application.rb ├── blazer.yml ├── boot.rb ├── coverband.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── i18n-tasks.yml ├── initializers │ ├── acts_as_taggable_on.rb │ ├── ahoy.rb │ ├── ahoy_email.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── blazer.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── cors.rb │ ├── disable_sprockets_concurrency.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── permissions_policy.rb │ ├── rails_email_preview.rb │ ├── shinycms.rb │ ├── sidekiq.rb │ └── version.rb ├── locales │ └── en.yml ├── puma.rb ├── routes.rb ├── sidekiq.yml └── storage.yml ├── db ├── archived-migrations │ ├── 20191014193220_devise_create_users.rb │ ├── 20191109152134_create_sessions.rb │ ├── 20191127225110_create_feature_flags.rb │ ├── 20191206184800_create_capability_categories.rb │ ├── 20191206184808_create_capabilities.rb │ ├── 20191206184835_create_user_capabilities.rb │ ├── 20191210211946_create_active_storage_tables.active_storage.rb │ ├── 20191217175907_add_index_to_user_capabilities.rb │ ├── 20200129202522_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb │ ├── 20200129202523_add_missing_unique_indices.acts_as_taggable_on_engine.rb │ ├── 20200129202524_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb │ ├── 20200129202525_add_missing_taggable_index.acts_as_taggable_on_engine.rb │ ├── 20200129202526_change_collation_for_tag_names.acts_as_taggable_on_engine.rb │ ├── 20200129202527_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb │ ├── 20200203230336_drop_settings.rb │ ├── 20200203231532_create_settings.rb │ ├── 20200205211726_create_setting_values.rb │ ├── 20200218155447_add_discussions.rb │ ├── 20200218155902_add_comments.rb │ ├── 20200227220410_rename_author_id_to_user_id_in_comments.rb │ ├── 20200302203545_add_ip_address_to_comments.rb │ ├── 20200308113704_create_ahoy_visits_and_events.rb │ ├── 20200310005145_create_email_recipients.rb │ ├── 20200315024923_install_blazer.rb │ ├── 20200324174621_add_unique_index_to_comments.rb │ ├── 20200324174637_add_unique_index_to_setting_values.rb │ ├── 20200326020927_add_canonical_email_to_users.rb │ ├── 20200327000512_create_consents.rb │ ├── 20200327014155_create_do_not_contacts.rb │ ├── 20200409180906_create_ahoy_messages.rb │ ├── 20200422183132_create_pg_search_documents.rb │ ├── 20200630142104_acts_as_votable_migration.rb │ ├── 20200702204022_create_votable_ips.rb │ ├── 20200724182808_fix_foreign_key_types.rb │ ├── 20200724210954_drop_unused_foreign_keys.rb │ ├── 20200802201259_rename_hidden_flags.rb │ ├── 20200813090405_change_display_name_to_public_name.rb │ ├── 20200905192113_create_consent_versions.rb │ ├── 20200915212009_create_shiny_blog_posts.shiny_blog.rb │ ├── 20200915212017_create_shiny_forms_forms.shiny_forms.rb │ ├── 20200915212037_create_shiny_news_posts.shiny_news.rb │ ├── 20200915212042_add_tables_for_shiny_pages.shiny_pages.rb │ ├── 20200915220517_add_shiny_inserts_tables.shiny_inserts.rb │ ├── 20200915220751_add_shiny_lists_tables.shiny_lists.rb │ ├── 20200915225123_create_shiny_newsletters_tables.shiny_newsletters.rb │ ├── 20201001180612_add_confirm_to_email_recipient.rb │ ├── 20201004134541_create_comment_authors.rb │ ├── 20201004150130_change_comment_author_to_polymorphic.rb │ ├── 20201007212946_add_deleted_at_to_user.rb │ ├── 20201008220616_add_deleted_at_to_blog_post.shiny_blog.rb │ ├── 20201008220622_add_deleted_at_to_news_post.shiny_news.rb │ ├── 20201008233537_add_deleted_at_to_discussion.rb │ ├── 20201008233543_add_deleted_at_to_comment.rb │ ├── 20201008234150_add_deleted_at_to_comment_author.rb │ ├── 20201008234156_add_deleted_at_to_consent_version.rb │ ├── 20201008234205_add_deleted_at_to_do_not_contact.rb │ ├── 20201008234213_add_deleted_at_to_feature_flag.rb │ ├── 20201008235031_add_deleted_at_to_email_recipient.rb │ ├── 20201009125021_add_deleted_at_to_forms.shiny_forms.rb │ ├── 20201009125026_add_deleted_at_to_lists_and_subscriptions.shiny_lists.rb │ ├── 20201009125033_add_deleted_at_to_insert_sets_and_elements.shiny_inserts.rb │ ├── 20201009144825_add_deleted_at_to_capabilities.rb │ ├── 20201009144833_add_deleted_at_to_settings.rb │ ├── 20201009163432_add_deleted_at_to_page_tables.shiny_pages.rb │ ├── 20201009163441_add_deleted_at_to_newsletter_tables.shiny_newsletters.rb │ ├── 20201009164412_add_deleted_at_to_user_capabilities.rb │ ├── 20201031050440_add_bot_protection_booleans_to_forms.shiny_forms.rb │ ├── 20201111195416_create_shiny_access_tables.shiny_access.rb │ ├── 20201130234759_create_shiny_profiles_tables.shiny_profiles.rb │ ├── 20201206144100_add_missing_indexes.rb │ ├── 20201227180916_add_service_name_to_active_storage_blobs.active_storage.rb │ └── 20201227180917_create_active_storage_variant_records.active_storage.rb ├── migrate │ ├── 20210226024355_rename_comment_authors.shiny_cms.rb │ ├── 20210226051341_create_shinycms_anonymous_authors.shiny_cms.rb │ ├── 20210226060425_rename_website_column.shiny_cms.rb │ ├── 20241106184645_index_ahoy_visits.shiny_cms.rb │ ├── 20250206162501_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20250206162502_create_active_storage_variant_records.active_storage.rb │ └── 20250206162503_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb ├── schema.rb └── seeds.rb ├── docs ├── CNAME ├── Cloud-Hosting.md ├── Configuration.md ├── Contributing.md ├── Contributors.md ├── Developers │ ├── Concerns-and-Helpers.md │ ├── Mailers.md │ ├── Notes │ │ ├── bullet.md │ │ ├── import-from-perl-shinycms.md │ │ ├── kloc.txt │ │ ├── mailing-list-notes.md │ │ ├── menu-icons.md │ │ ├── needs-indexing.md │ │ ├── new-site.md │ │ ├── packwerk.log │ │ ├── plugin-sizes.md │ │ └── user-personas.md │ ├── Plugins.md │ ├── ProjectGoals.md │ ├── TODO.md │ ├── Testing.md │ ├── code-quality.md │ ├── controller-concerns.md │ ├── demo-data.md │ ├── done.md │ ├── helpers.md │ ├── in-progress.md │ ├── index.md │ ├── model-concerns.md │ ├── other-modules.md │ └── rake-tasks.md ├── Features │ ├── MainApp │ │ ├── Charts.md │ │ ├── Comments.md │ │ ├── EmailStats.md │ │ ├── FeatureFlags.md │ │ ├── SiteSettings.md │ │ ├── Tags.md │ │ ├── Upvotes.md │ │ ├── UserAccounts.md │ │ ├── WebStats.md │ │ ├── admin-features.md │ │ ├── mjml.md │ │ ├── pagination.md │ │ ├── rack-attack.md │ │ └── soft-delete.md │ └── Plugins │ │ ├── ShinyAccess.md │ │ ├── ShinyBlog.md │ │ ├── ShinyForms.md │ │ ├── ShinyInserts.md │ │ ├── ShinyLists.md │ │ ├── ShinyNews.md │ │ ├── ShinyNewsletters.md │ │ ├── ShinyPages.md │ │ ├── ShinyProfiles.md │ │ └── ShinySearch.md ├── INSTALL.md ├── Licensing │ ├── cc-by-3.0.txt │ ├── gnu-gpl-v2.0.md │ ├── gnu-gpl-v3.0.md │ ├── index.md │ └── mit.md ├── Services.md ├── Themes.md ├── code-of-conduct.md ├── create-blazer-db-user.sql ├── demo-site.md ├── env.sample ├── index.md ├── rake-tasks.md ├── release-notes.md └── tldr.md ├── lib ├── generators │ └── shiny │ │ └── plugin │ │ ├── USAGE │ │ ├── plugin_builder.rb │ │ ├── plugin_generator.rb │ │ └── plugin_generator_base.rb └── templates │ └── shiny │ └── plugin │ ├── %name%.gemspec.tt │ ├── Gemfile │ ├── LICENSE │ ├── README.md.tt │ ├── Rakefile.tt │ ├── app │ ├── controllers │ │ └── %namespaced_name% │ │ │ ├── admin_controller.rb.tt │ │ │ ├── application_controller.rb.tt │ │ │ └── main_controller.rb.tt │ ├── helpers │ │ └── %namespaced_name% │ │ │ └── application_helper.rb.tt │ ├── jobs │ │ └── %namespaced_name% │ │ │ └── application_job.rb.tt │ ├── mailers │ │ └── %namespaced_name% │ │ │ └── application_mailer.rb.tt │ ├── models │ │ └── %namespaced_name% │ │ │ └── application_record.rb.tt │ └── views │ │ └── %namespaced_name% │ │ └── admin │ │ └── menu │ │ └── _section.html.erb.tt │ ├── bin │ └── rails.tt │ ├── config │ ├── locales │ │ └── en.yml.tt │ └── routes.rb.tt │ ├── gitignore.tt │ ├── lib │ ├── %namespaced_name%.rb.tt │ ├── %namespaced_name% │ │ ├── engine.rb.tt │ │ └── version.rb.tt │ └── tasks │ │ └── %namespaced_name%_tasks.rake.tt │ └── rails │ ├── application.rb.tt │ ├── boot.rb.tt │ ├── engine_manifest.js.tt │ ├── javascripts.js.tt │ ├── routes.rb.tt │ └── stylesheets.css ├── log └── .keep ├── mkdocs.yml ├── package.json ├── package.yml ├── packwerk.yml ├── plugins ├── ShinyAccess │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_access │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_access │ │ │ │ ├── admin │ │ │ │ ├── groups_controller.rb │ │ │ │ └── memberships_controller.rb │ │ │ │ └── application_controller.rb │ │ ├── helpers │ │ │ └── shiny_access │ │ │ │ └── main_site_helper.rb │ │ ├── jobs │ │ │ └── shiny_access │ │ │ │ └── application_job.rb │ │ ├── mailers │ │ │ └── shiny_access │ │ │ │ └── application_mailer.rb │ │ ├── models │ │ │ └── shiny_access │ │ │ │ ├── application_record.rb │ │ │ │ ├── group.rb │ │ │ │ └── membership.rb │ │ ├── policies │ │ │ └── shiny_access │ │ │ │ ├── group_policy.rb │ │ │ │ └── membership_policy.rb │ │ └── views │ │ │ └── shiny_access │ │ │ └── admin │ │ │ ├── groups │ │ │ ├── edit.html.erb │ │ │ ├── index.html.erb │ │ │ └── new.html.erb │ │ │ └── memberships │ │ │ └── index.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ └── 20201111033231_create_shiny_access_tables.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_access.rb │ │ ├── shiny_access │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_access_tasks.rake │ ├── package.yml │ ├── shiny_access.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_access │ │ │ ├── groups.rb │ │ │ └── memberships.rb │ │ └── users.rb │ │ ├── helpers │ │ └── shiny_access │ │ │ └── main_site_helper_spec.rb │ │ ├── models │ │ └── shiny_access │ │ │ ├── group_spec.rb │ │ │ └── membership_spec.rb │ │ └── requests │ │ └── shiny_access │ │ └── admin │ │ ├── groups_controller_spec.rb │ │ └── memberships_controller_spec.rb ├── ShinyBlog │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_blog │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_blog │ │ │ │ ├── admin │ │ │ │ └── blog_posts_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── blog_controller.rb │ │ ├── helpers │ │ │ └── shiny_blog │ │ │ │ └── main_site_helper.rb │ │ ├── jobs │ │ │ └── shiny_blog │ │ │ │ ├── application_job.rb │ │ │ │ └── build_atom_feed_job.rb │ │ ├── models │ │ │ └── shiny_blog │ │ │ │ ├── application_record.rb │ │ │ │ └── post.rb │ │ ├── policies │ │ │ └── shiny_blog │ │ │ │ └── post_policy.rb │ │ └── views │ │ │ └── shiny_blog │ │ │ ├── admin │ │ │ ├── blog_posts │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── toolbar │ │ │ │ └── _section.html.erb │ │ │ └── user │ │ │ │ └── _edit_capabilities.html.erb │ │ │ ├── blog │ │ │ ├── _right_sidebar_join.html.erb │ │ │ ├── _sidebar.html.erb │ │ │ ├── index.html.erb │ │ │ ├── index │ │ │ │ ├── _page_title.html.erb │ │ │ │ ├── _post_footer.html.erb │ │ │ │ └── _post_header.html.erb │ │ │ ├── month.html.erb │ │ │ ├── show.html.erb │ │ │ ├── show │ │ │ │ ├── _comment_form.html.erb │ │ │ │ ├── _discussion.html.erb │ │ │ │ ├── _footer_discussion_links.html.erb │ │ │ │ ├── _footer_votable_links.html.erb │ │ │ │ ├── _post_footer.html.erb │ │ │ │ ├── _post_header.html.erb │ │ │ │ └── _post_tags.html.erb │ │ │ └── year.html.erb │ │ │ ├── includes │ │ │ └── _head_part.html.erb │ │ │ ├── menu │ │ │ └── _section.html.erb │ │ │ ├── profile │ │ │ └── _content.html.erb │ │ │ └── search │ │ │ └── result │ │ │ └── shiny_blog │ │ │ └── _post.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200812233918_create_shiny_blog_posts.rb │ │ │ └── 20201008220226_add_deleted_at_to_blog_post.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_blog.rb │ │ ├── shiny_blog │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_blog_tasks.rake │ ├── package.yml │ ├── shiny_blog.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_blog │ │ │ └── blog_posts.rb │ │ └── users.rb │ │ ├── jobs │ │ └── shiny_blog │ │ │ └── build_atom_feed_job_spec.rb │ │ ├── models │ │ └── shiny_blog │ │ │ └── post_spec.rb │ │ └── requests │ │ └── shiny_blog │ │ ├── admin │ │ └── blog_posts_controllers_spec.rb │ │ └── blog_controller_spec.rb ├── ShinyCMS │ ├── .rubocop.yml │ ├── .rubocop_todo.yml │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── assets │ │ │ ├── config │ │ │ │ └── shinycms_manifest.js │ │ │ ├── images │ │ │ │ └── shinycms │ │ │ │ │ ├── ShinyCMS-logo.png │ │ │ │ │ ├── admin-toolbar │ │ │ │ │ ├── bg.png │ │ │ │ │ └── logo.png │ │ │ │ │ ├── favicon.ico │ │ │ │ │ └── spiral.png │ │ │ └── stylesheets │ │ │ │ └── shinycms │ │ │ │ ├── admin_area.scss │ │ │ │ ├── admin_toolbar.scss │ │ │ │ ├── index.css │ │ │ │ └── main_site.scss │ │ ├── components │ │ │ └── shinycms │ │ │ │ ├── admin │ │ │ │ ├── alert_component.html.erb │ │ │ │ ├── alert_component.rb │ │ │ │ ├── alerts_component.html.erb │ │ │ │ ├── alerts_component.rb │ │ │ │ ├── breadcrumb_item_component.html.erb │ │ │ │ ├── breadcrumb_item_component.rb │ │ │ │ ├── breadcrumbs_component.html.erb │ │ │ │ ├── breadcrumbs_component.rb │ │ │ │ ├── head │ │ │ │ │ ├── blazer_component.html.erb │ │ │ │ │ ├── blazer_component.rb │ │ │ │ │ └── title_component.rb │ │ │ │ ├── head_component.html.erb │ │ │ │ ├── head_component.rb │ │ │ │ ├── menu │ │ │ │ │ ├── consent_versions_component.html.erb │ │ │ │ │ ├── consent_versions_component.rb │ │ │ │ │ ├── coverband_component.html.erb │ │ │ │ │ ├── coverband_component.rb │ │ │ │ │ ├── email_component.html.erb │ │ │ │ │ ├── email_component.rb │ │ │ │ │ ├── item_component.html.erb │ │ │ │ │ ├── item_component.rb │ │ │ │ │ ├── other_component.html.erb │ │ │ │ │ ├── other_component.rb │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ ├── section_component.rb │ │ │ │ │ ├── settings_component.html.erb │ │ │ │ │ ├── settings_component.rb │ │ │ │ │ ├── sidekiq_component.html.erb │ │ │ │ │ ├── sidekiq_component.rb │ │ │ │ │ ├── stats_component.html.erb │ │ │ │ │ ├── stats_component.rb │ │ │ │ │ ├── users_component.html.erb │ │ │ │ │ └── users_component.rb │ │ │ │ ├── menu_component.html.erb │ │ │ │ ├── menu_component.rb │ │ │ │ ├── sidebar_component.html.erb │ │ │ │ ├── sidebar_component.rb │ │ │ │ ├── user_menu_component.html.erb │ │ │ │ └── user_menu_component.rb │ │ │ │ ├── application_component.rb │ │ │ │ ├── head │ │ │ │ └── title_component.rb │ │ │ │ └── toolbar │ │ │ │ ├── discussions_component.html.erb │ │ │ │ ├── discussions_component.rb │ │ │ │ ├── users_component.html.erb │ │ │ │ └── users_component.rb │ │ ├── controllers │ │ │ ├── concerns │ │ │ │ └── shinycms │ │ │ │ │ ├── admin │ │ │ │ │ └── access_control_by_ip.rb │ │ │ │ │ ├── password_report_action.rb │ │ │ │ │ ├── with_feature_flags.rb │ │ │ │ │ └── with_votes.rb │ │ │ └── shinycms │ │ │ │ ├── admin │ │ │ │ ├── comments_controller.rb │ │ │ │ ├── consent_versions_controller.rb │ │ │ │ ├── discussions_controller.rb │ │ │ │ ├── email_recipients_controller.rb │ │ │ │ ├── email_stats_controller.rb │ │ │ │ ├── feature_flags_controller.rb │ │ │ │ ├── root_controller.rb │ │ │ │ ├── site_settings_controller.rb │ │ │ │ ├── tools │ │ │ │ │ └── rails_email_preview_base_controller.rb │ │ │ │ ├── users_controller.rb │ │ │ │ └── web_stats_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ ├── comments_controller.rb │ │ │ │ ├── discussions_controller.rb │ │ │ │ ├── do_not_contact_controller.rb │ │ │ │ ├── email_recipients_controller.rb │ │ │ │ ├── errors_controller.rb │ │ │ │ ├── site_settings_controller.rb │ │ │ │ ├── tags_controller.rb │ │ │ │ ├── users │ │ │ │ ├── base_controller.rb │ │ │ │ ├── confirmations_controller.rb │ │ │ │ ├── passwords_controller.rb │ │ │ │ ├── registrations_controller.rb │ │ │ │ ├── sessions_controller.rb │ │ │ │ └── unlocks_controller.rb │ │ │ │ └── votes_controller.rb │ │ ├── helpers │ │ │ └── shinycms │ │ │ │ ├── admin_area_helper.rb │ │ │ │ ├── consent_helper.rb │ │ │ │ ├── dates_helper.rb │ │ │ │ ├── discussions_helper.rb │ │ │ │ ├── elements_helper.rb │ │ │ │ ├── feature_flags_helper.rb │ │ │ │ ├── main_site_helper.rb │ │ │ │ ├── plugins_helper.rb │ │ │ │ ├── site_name_helper.rb │ │ │ │ ├── tags_helper.rb │ │ │ │ └── users_helper.rb │ │ ├── lib │ │ │ └── shinycms │ │ │ │ ├── akismet_client.rb │ │ │ │ └── route_delegator.rb │ │ ├── mailer_previews │ │ │ └── shinycms │ │ │ │ ├── discussion_mailer_preview.rb │ │ │ │ └── user_mailer_preview.rb │ │ ├── mailers │ │ │ └── shinycms │ │ │ │ ├── application_mailer.rb │ │ │ │ ├── discussion_mailer.rb │ │ │ │ ├── email_recipient_mailer.rb │ │ │ │ ├── setup_for_base_mailer.rb │ │ │ │ └── user_mailer.rb │ │ ├── models │ │ │ ├── concerns │ │ │ │ └── shinycms │ │ │ │ │ ├── has_email.rb │ │ │ │ │ ├── has_tags.rb │ │ │ │ │ ├── has_teaser.rb │ │ │ │ │ ├── has_token.rb │ │ │ │ │ ├── has_votes.rb │ │ │ │ │ ├── plugins_components.rb │ │ │ │ │ ├── shiny_user_authentication.rb │ │ │ │ │ ├── shiny_user_authorization.rb │ │ │ │ │ └── shiny_user_content.rb │ │ │ └── shinycms │ │ │ │ ├── anonymous_author.rb │ │ │ │ ├── application_record.rb │ │ │ │ ├── atom_feed.rb │ │ │ │ ├── atom_feed_entry.rb │ │ │ │ ├── capability.rb │ │ │ │ ├── capability_category.rb │ │ │ │ ├── comment.rb │ │ │ │ ├── discussion.rb │ │ │ │ ├── do_not_contact.rb │ │ │ │ ├── feature_flag.rb │ │ │ │ ├── plugin.rb │ │ │ │ ├── plugins.rb │ │ │ │ ├── pseudonymous_author.rb │ │ │ │ ├── setting.rb │ │ │ │ ├── setting_value.rb │ │ │ │ ├── user.rb │ │ │ │ ├── user_capability.rb │ │ │ │ └── votable_ip.rb │ │ ├── policies │ │ │ └── shinycms │ │ │ │ ├── comment_policy.rb │ │ │ │ ├── consent_version_policy.rb │ │ │ │ ├── discussion_policy.rb │ │ │ │ ├── email_recipient_policy.rb │ │ │ │ ├── feature_flag_policy.rb │ │ │ │ ├── mailer_preview_policy.rb │ │ │ │ ├── setting_policy.rb │ │ │ │ └── user_policy.rb │ │ ├── public │ │ │ ├── components │ │ │ │ └── concerns │ │ │ │ │ └── shinycms │ │ │ │ │ └── view_component_base.rb │ │ │ ├── controllers │ │ │ │ ├── concerns │ │ │ │ │ └── shinycms │ │ │ │ │ │ ├── admin │ │ │ │ │ │ ├── with_date_time_inputs.rb │ │ │ │ │ │ ├── with_discussions.rb │ │ │ │ │ │ ├── with_posts.rb │ │ │ │ │ │ ├── with_sorting.rb │ │ │ │ │ │ └── with_tags.rb │ │ │ │ │ │ ├── admin_area_controller_base.rb │ │ │ │ │ │ ├── controller_base.rb │ │ │ │ │ │ ├── main_site_controller_base.rb │ │ │ │ │ │ ├── with_email_recipients.rb │ │ │ │ │ │ └── with_settings.rb │ │ │ │ └── shinycms │ │ │ │ │ └── admin │ │ │ │ │ └── tools │ │ │ │ │ ├── base_controller.rb │ │ │ │ │ └── blazer_base_controller.rb │ │ │ ├── helpers │ │ │ │ └── shinycms │ │ │ │ │ ├── settings_helper.rb │ │ │ │ │ └── view_component_helper.rb │ │ │ ├── lib │ │ │ │ └── shinycms │ │ │ │ │ ├── main_app_root_url.rb │ │ │ │ │ ├── routes │ │ │ │ │ ├── admin_404.rb │ │ │ │ │ ├── admin_concerns.rb │ │ │ │ │ └── plugins.rb │ │ │ │ │ ├── seeder.rb │ │ │ │ │ ├── with_akismet.rb │ │ │ │ │ ├── with_consent_version.rb │ │ │ │ │ ├── with_recaptcha.rb │ │ │ │ │ └── with_users.rb │ │ │ ├── mailers │ │ │ │ └── shinycms │ │ │ │ │ └── base_mailer.rb │ │ │ ├── models │ │ │ │ ├── concerns │ │ │ │ │ └── shinycms │ │ │ │ │ │ ├── can_hide.rb │ │ │ │ │ │ ├── element.rb │ │ │ │ │ │ ├── has_public_name.rb │ │ │ │ │ │ ├── has_readable_name.rb │ │ │ │ │ │ ├── has_slug.rb │ │ │ │ │ │ ├── has_slug_unique_in_month.rb │ │ │ │ │ │ ├── has_slug_unique_in_section.rb │ │ │ │ │ │ ├── has_template.rb │ │ │ │ │ │ ├── html_template.rb │ │ │ │ │ │ ├── mjml_template.rb │ │ │ │ │ │ ├── post.rb │ │ │ │ │ │ ├── provides_demo_site_data.rb │ │ │ │ │ │ ├── provides_sitemap_data.rb │ │ │ │ │ │ ├── soft_delete.rb │ │ │ │ │ │ ├── template.rb │ │ │ │ │ │ ├── template_element.rb │ │ │ │ │ │ └── username_validation.rb │ │ │ │ └── shinycms │ │ │ │ │ ├── consent_version.rb │ │ │ │ │ ├── email_recipient.rb │ │ │ │ │ ├── s3_config.rb │ │ │ │ │ └── theme.rb │ │ │ └── services │ │ │ │ └── shinycms │ │ │ │ └── atom_feed_builder.rb │ │ └── views │ │ │ └── shinycms │ │ │ ├── admin │ │ │ ├── comments │ │ │ │ └── index.html.erb │ │ │ ├── consent_versions │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ ├── new.html.erb │ │ │ │ └── show.html.erb │ │ │ ├── email_recipients │ │ │ │ └── index.html.erb │ │ │ ├── email_stats │ │ │ │ └── index.html.erb │ │ │ ├── feature_flags │ │ │ │ └── index.html.erb │ │ │ ├── includes │ │ │ │ ├── _admin_toolbar.html.erb │ │ │ │ ├── _pager.html.erb │ │ │ │ └── _search.html.erb │ │ │ ├── layouts │ │ │ │ └── admin_area.html.erb │ │ │ ├── site_settings │ │ │ │ └── index.html.erb │ │ │ ├── users │ │ │ │ ├── _capability_category.html.erb │ │ │ │ ├── _capability_checkbox.html.erb │ │ │ │ ├── _edit_capabilities.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ └── web_stats │ │ │ │ └── index.html.erb │ │ │ ├── comments │ │ │ ├── _comment.html.erb │ │ │ ├── _comment_form.html.erb │ │ │ ├── _comment_thread.html.erb │ │ │ ├── _hidden_comment.html.erb │ │ │ ├── comment │ │ │ │ ├── _footer.html.erb │ │ │ │ ├── _header.erb │ │ │ │ ├── _moderation_links.html.erb │ │ │ │ └── _posted_by.html.erb │ │ │ ├── index.html.erb │ │ │ ├── new.html.erb │ │ │ ├── profile │ │ │ │ └── _content.html.erb │ │ │ └── show.html.erb │ │ │ ├── devise │ │ │ ├── confirmations │ │ │ │ └── new.html.erb │ │ │ ├── passwords │ │ │ │ ├── edit.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── registrations │ │ │ │ ├── edit.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── sessions │ │ │ │ └── new.html.erb │ │ │ ├── shared │ │ │ │ ├── _error_messages.html.erb │ │ │ │ └── _links.html.erb │ │ │ └── unlocks │ │ │ │ └── new.html.erb │ │ │ ├── discussion_mailer │ │ │ ├── _comment.html.mjml │ │ │ ├── comment_admin_notification.html.mjml │ │ │ ├── comment_admin_notification.text.erb │ │ │ ├── content_author_notification.html.mjml │ │ │ ├── content_author_notification.text.erb │ │ │ ├── parent_comment_author_notification.html.mjml │ │ │ └── parent_comment_author_notification.text.erb │ │ │ ├── discussions │ │ │ ├── _discussion.html.erb │ │ │ ├── _moderation_links.html.erb │ │ │ ├── _top_level.html.erb │ │ │ ├── index.html.erb │ │ │ └── show.html.erb │ │ │ ├── do_not_contact │ │ │ └── new.html.erb │ │ │ ├── email_recipient_mailer │ │ │ ├── confirm.html.mjml │ │ │ └── confirm.text.erb │ │ │ ├── errors │ │ │ ├── internal_server_error.html.erb │ │ │ └── not_found.html.erb │ │ │ ├── includes │ │ │ ├── _footer.html.erb │ │ │ ├── _footer_javascript.html.erb │ │ │ ├── _head.html.erb │ │ │ ├── _messages.html.erb │ │ │ ├── _newer_older_pager.html.erb │ │ │ ├── _pager.html.erb │ │ │ ├── _recaptcha_tags.html.erb │ │ │ └── _sidebar.html.erb │ │ │ ├── layouts │ │ │ ├── mailer.html.mjml │ │ │ ├── mailer.text.erb │ │ │ └── main_site.html.erb │ │ │ ├── menu │ │ │ ├── _menu.html.erb │ │ │ └── _tags.html.erb │ │ │ ├── posts │ │ │ └── show │ │ │ │ └── _next_and_previous_post_links.html.erb │ │ │ ├── rails_email_preview │ │ │ └── emails │ │ │ │ ├── _email_iframe.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── show.html.erb │ │ │ ├── site_settings │ │ │ └── index.html.erb │ │ │ ├── tags │ │ │ ├── cloud.html.erb │ │ │ ├── list.html.erb │ │ │ └── show.html.erb │ │ │ ├── user_mailer │ │ │ ├── confirmation_instructions.html.mjml │ │ │ ├── confirmation_instructions.text.erb │ │ │ ├── email_changed_instructions.html.mjml │ │ │ ├── email_changed_instructions.text.erb │ │ │ ├── password_changed_instructions.html.mjml │ │ │ ├── password_changed_instructions.text.erb │ │ │ ├── reset_password_instructions.html.mjml │ │ │ ├── reset_password_instructions.text.erb │ │ │ ├── unlock_instructions.html.mjml │ │ │ └── unlock_instructions.text.erb │ │ │ └── votable │ │ │ ├── _vote_up.html.erb │ │ │ └── _vote_up_down.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── coverband.rb │ │ ├── initializers │ │ │ ├── activerecord_timestamp_precision.rb │ │ │ ├── airbrake.rb │ │ │ ├── assets.rb │ │ │ ├── blazer.rb │ │ │ ├── ckeditor.rb │ │ │ ├── devise.rb │ │ │ ├── field_with_errors.rb │ │ │ ├── html_sanitizer.rb │ │ │ ├── i18n.rb │ │ │ ├── inflections.rb │ │ │ ├── inflections.rb.new │ │ │ ├── pagy.rb │ │ │ ├── rack_attack.rb │ │ │ ├── rails_email_preview.rb │ │ │ ├── rails_reloader.rb │ │ │ ├── rspec_generators.rb │ │ │ ├── scout_apm.yml │ │ │ ├── sentry.rb │ │ │ ├── sessions.rb │ │ │ └── time_formats.rb │ │ ├── locales │ │ │ ├── devise.en.yml │ │ │ └── en.yml │ │ ├── routes.rb │ │ └── routes │ │ │ ├── admin_area.rb │ │ │ ├── main_site.rb │ │ │ └── tools.rb │ ├── db │ │ ├── demo_site_data.rb │ │ ├── migrate │ │ │ ├── 20210226020652_rename_comment_authors.rb │ │ │ ├── 20210226050046_create_shinycms_anonymous_authors.rb │ │ │ ├── 20210226060005_rename_website_column.rb │ │ │ └── 20241106060001_index_ahoy_visits.rb │ │ ├── seeds.rb │ │ └── seeds │ │ │ ├── blazer.rb │ │ │ ├── capabilities.rb │ │ │ ├── feature_flags.rb │ │ │ └── settings.rb │ ├── lib │ │ ├── shinycms.rb │ │ ├── shinycms │ │ │ ├── engine.rb │ │ │ ├── gemfile_helper.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ ├── admin_user.rake │ │ │ ├── demo_site.rake │ │ │ ├── feature.rake │ │ │ ├── sessions.rake │ │ │ ├── shinycms_tasks.rake │ │ │ └── support │ │ │ ├── admin_user_task.rb │ │ │ └── demo_site_task.rb │ ├── package.yml │ ├── package_todo.yml │ ├── shinycms.gemspec │ ├── spec │ │ ├── controllers │ │ │ └── concerns │ │ │ │ └── shinycms │ │ │ │ └── admin │ │ │ │ └── with_tags_spec.rb │ │ ├── factories │ │ │ └── shinycms │ │ │ │ ├── anonymous_authors.rb │ │ │ │ ├── capabilities.rb │ │ │ │ ├── capability_categories.rb │ │ │ │ ├── comments.rb │ │ │ │ ├── consent_versions.rb │ │ │ │ ├── discussions.rb │ │ │ │ ├── do_not_contacts.rb │ │ │ │ ├── email_recipients.rb │ │ │ │ ├── feature_flags.rb │ │ │ │ ├── pseudonymous_authors.rb │ │ │ │ ├── setting_values.rb │ │ │ │ ├── settings.rb │ │ │ │ ├── user_capabilities.rb │ │ │ │ ├── users.rb │ │ │ │ └── votable_ips.rb │ │ ├── fixtures │ │ │ └── TEST │ │ │ │ └── views │ │ │ │ ├── shiny_forms │ │ │ │ └── form_mailer │ │ │ │ │ ├── contact_form.html.mjml │ │ │ │ │ └── contact_form.text.erb │ │ │ │ ├── shiny_newsletters │ │ │ │ └── newsletter_mailer │ │ │ │ │ ├── an_example.html.mjml │ │ │ │ │ ├── an_example.text.erb │ │ │ │ │ └── bad_mjml.html.mjml │ │ │ │ └── shiny_pages │ │ │ │ └── pages │ │ │ │ ├── an_example.html.erb │ │ │ │ └── contact_form.html.erb │ │ ├── helpers │ │ │ └── shinycms │ │ │ │ ├── date_helper_spec.rb │ │ │ │ ├── main_site_helper_spec.rb │ │ │ │ ├── plugins_helper_spec.rb │ │ │ │ └── users_helper_spec.rb │ │ ├── lib │ │ │ └── shinycms │ │ │ │ └── route_delegator_spec.rb │ │ ├── mailer_previews │ │ │ └── shinycms │ │ │ │ ├── discussion_mailer_preview_spec.rb │ │ │ │ └── user_mailer_preview_spec.rb │ │ ├── mailers │ │ │ └── shinycms │ │ │ │ ├── discussion_mailer_spec.rb │ │ │ │ ├── email_recipient_mailer_spec.rb │ │ │ │ └── user_mailer_spec.rb │ │ ├── models │ │ │ ├── concerns │ │ │ │ └── shinycms │ │ │ │ │ └── shiny_user_authentication_spec.rb │ │ │ └── shinycms │ │ │ │ ├── anonymous_author_spec.rb │ │ │ │ ├── capability_spec.rb │ │ │ │ ├── comment_spec.rb │ │ │ │ ├── consent_version_spec.rb │ │ │ │ ├── discussion_spec.rb │ │ │ │ ├── do_not_contact_spec.rb │ │ │ │ ├── email_recipient_spec.rb │ │ │ │ ├── feature_flag_spec.rb │ │ │ │ ├── plugin_spec.rb │ │ │ │ ├── plugins_components_spec.rb │ │ │ │ ├── plugins_spec.rb │ │ │ │ ├── pseudonymous_author_spec.rb │ │ │ │ ├── s3_config_spec.rb │ │ │ │ ├── setting_spec.rb │ │ │ │ ├── theme_spec.rb │ │ │ │ ├── user_spec.rb │ │ │ │ └── votable_ip_spec.rb │ │ ├── other │ │ │ ├── demo_site_task_spec.rb │ │ │ └── i18n_spec.rb │ │ ├── rails_helper.rb │ │ ├── requests │ │ │ └── shinycms │ │ │ │ ├── admin │ │ │ │ ├── comments_controller_spec.rb │ │ │ │ ├── consent_versions_controller_spec.rb │ │ │ │ ├── discussions_controller_spec.rb │ │ │ │ ├── email_recipients_controller_spec.rb │ │ │ │ ├── email_stats_controller_spec.rb │ │ │ │ ├── feature_flags_controller_spec.rb │ │ │ │ ├── site_settings_controller_spec.rb │ │ │ │ ├── tools │ │ │ │ │ ├── blazer_base_controller_spec.rb │ │ │ │ │ └── rails_email_preview_spec.rb │ │ │ │ ├── users_controller_spec.rb │ │ │ │ └── web_stats_controller_spec.rb │ │ │ │ ├── admin_controller_spec.rb │ │ │ │ ├── comments_controller_spec.rb │ │ │ │ ├── discussions_controller_spec.rb │ │ │ │ ├── do_not_contact_controller_spec.rb │ │ │ │ ├── email_recipients_controller_spec.rb │ │ │ │ ├── errors_controller_spec.rb │ │ │ │ ├── feature_flags_controller_spec.rb │ │ │ │ ├── site_settings_controller_spec.rb │ │ │ │ ├── tags_controller_spec.rb │ │ │ │ ├── users │ │ │ │ ├── confirmations_controller_spec.rb │ │ │ │ ├── password_report_action_spec.rb │ │ │ │ ├── passwords_controller_spec.rb │ │ │ │ ├── registrations_controller_spec.rb │ │ │ │ ├── sessions_controller_spec.rb │ │ │ │ └── unlocks_controller_spec.rb │ │ │ │ └── votes_controller_spec.rb │ │ ├── spec_helper.rb │ │ └── support │ │ │ ├── factory_bot.rb │ │ │ ├── faker.rb │ │ │ ├── shared_examples │ │ │ ├── shinycms │ │ │ │ ├── comment_author_example.rb │ │ │ │ ├── element_example.rb │ │ │ │ ├── has_email_example.rb │ │ │ │ ├── has_public_name_example.rb │ │ │ │ ├── has_slug_example.rb │ │ │ │ ├── has_token_example.rb │ │ │ │ ├── paging_example.rb │ │ │ │ ├── post_example.rb │ │ │ │ └── provides_demo_site_data_example.rb │ │ │ ├── voteable_example.rb │ │ │ └── voteable_voter_example.rb │ │ │ └── shinycms │ │ │ └── error_responses.rb │ └── vendor │ │ └── assets │ │ └── stylesheets │ │ ├── rails_email_preview │ │ ├── _bootstrap3.sass │ │ ├── _default.sass │ │ ├── _iframe.scss │ │ └── application.scss │ │ └── smartmenus │ │ ├── index.css │ │ ├── sm-blue │ │ ├── _mixins.scss │ │ ├── _sm-blue-theme.scss │ │ ├── mixins │ │ │ ├── _round-corners-last-item.scss │ │ │ └── _sub-items-indentation.scss │ │ ├── sm-blue.css.map │ │ └── sm-blue.scss │ │ ├── sm-clean │ │ ├── _mixins.scss │ │ ├── _sm-clean-theme.scss │ │ ├── mixins │ │ │ ├── _round-corners-last-item.scss │ │ │ └── _sub-items-indentation.scss │ │ ├── sm-clean.css.map │ │ └── sm-clean.scss │ │ ├── sm-core-css.css │ │ ├── sm-mint │ │ ├── _mixins.scss │ │ ├── _sm-mint-theme.scss │ │ ├── mixins │ │ │ └── _sub-items-indentation.scss │ │ ├── sm-mint.css.map │ │ └── sm-mint.scss │ │ └── sm-simple │ │ ├── _mixins.scss │ │ ├── _sm-simple-theme.scss │ │ ├── mixins │ │ └── _sub-items-indentation.scss │ │ ├── sm-simple.css.map │ │ └── sm-simple.scss ├── ShinyForms │ ├── .gitignore │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_forms │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_forms │ │ │ │ ├── admin │ │ │ │ └── forms_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── forms_controller.rb │ │ ├── helpers │ │ │ └── shiny_forms │ │ │ │ └── main_site_helper.rb │ │ ├── jobs │ │ │ └── shiny_forms │ │ │ │ └── application_job.rb │ │ ├── mailers │ │ │ └── shiny_forms │ │ │ │ ├── application_mailer.rb │ │ │ │ └── form_mailer.rb │ │ ├── models │ │ │ └── shiny_forms │ │ │ │ ├── application_record.rb │ │ │ │ ├── form.rb │ │ │ │ └── form_handler.rb │ │ ├── policies │ │ │ └── shiny_forms │ │ │ │ └── form_policy.rb │ │ └── views │ │ │ └── shiny_forms │ │ │ ├── admin │ │ │ ├── forms │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ └── toolbar │ │ │ │ └── _section.html.erb │ │ │ └── form_mailer │ │ │ ├── contact_form.html.mjml │ │ │ ├── contact_form.text.erb │ │ │ └── plain_email.text.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200730141332_create_shiny_forms_forms.rb │ │ │ ├── 20201009124440_add_deleted_at_to_forms.rb │ │ │ └── 20201031050301_add_bot_protection_booleans_to_forms.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_forms.rb │ │ ├── shiny_forms │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_forms_tasks.rake │ ├── package.yml │ ├── shiny_forms.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_forms │ │ │ └── forms.rb │ │ └── users.rb │ │ ├── mailers │ │ └── shiny_forms │ │ │ └── form_mailer_spec.rb │ │ ├── models │ │ └── shiny_forms │ │ │ └── form_spec.rb │ │ └── requests │ │ └── shiny_forms │ │ ├── admin │ │ └── forms_controller_spec.rb │ │ └── forms_controller_spec.rb ├── ShinyInserts │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── shiny_inserts │ │ │ │ ├── admin │ │ │ │ └── inserts_controller.rb │ │ │ │ └── application_controller.rb │ │ ├── helpers │ │ │ └── shiny_inserts │ │ │ │ └── main_site_helper.rb │ │ ├── models │ │ │ └── shiny_inserts │ │ │ │ ├── application_record.rb │ │ │ │ ├── element.rb │ │ │ │ └── set.rb │ │ ├── policies │ │ │ └── shiny_inserts │ │ │ │ ├── element_policy.rb │ │ │ │ └── set_policy.rb │ │ └── views │ │ │ └── shiny_inserts │ │ │ └── admin │ │ │ ├── inserts │ │ │ ├── _element.html.erb │ │ │ └── index.html.erb │ │ │ ├── menu │ │ │ └── _other_item.html.erb │ │ │ ├── toolbar │ │ │ └── _section.html.erb │ │ │ └── user │ │ │ └── _edit_capabilities.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200820224612_add_shiny_inserts_tables.rb │ │ │ └── 20201009124530_add_deleted_at_to_insert_sets_and_elements.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_inserts.rb │ │ ├── shiny_inserts │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_inserts_tasks.rake │ ├── package.yml │ ├── shiny_inserts.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_inserts │ │ │ └── insert_elements.rb │ │ └── users.rb │ │ ├── models │ │ └── shiny_inserts │ │ │ └── element_spec.rb │ │ └── requests │ │ └── shiny_inserts │ │ ├── admin │ │ └── inserts_controller_spec.rb │ │ └── inserts_controller_spec.rb ├── ShinyLists │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_lists │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_lists │ │ │ │ ├── admin │ │ │ │ ├── lists_controller.rb │ │ │ │ └── subscriptions_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── subscriptions_controller.rb │ │ ├── helpers │ │ │ └── shiny_lists │ │ │ │ └── main_site_helper.rb │ │ ├── models │ │ │ └── shiny_lists │ │ │ │ ├── application_record.rb │ │ │ │ ├── list.rb │ │ │ │ └── subscription.rb │ │ ├── policies │ │ │ └── shiny_lists │ │ │ │ ├── list_policy.rb │ │ │ │ └── subscription_policy.rb │ │ ├── public │ │ │ └── controllers │ │ │ │ └── concerns │ │ │ │ └── shiny_lists │ │ │ │ └── admin │ │ │ │ └── with_lists.rb │ │ └── views │ │ │ └── shiny_lists │ │ │ ├── admin │ │ │ ├── lists │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── subscriptions │ │ │ │ └── index.html.erb │ │ │ └── user │ │ │ │ └── _edit_capabilities.html.erb │ │ │ ├── includes │ │ │ ├── _subscription_form.html.erb │ │ │ └── email │ │ │ │ ├── _manage_subscriptions.html.mjml │ │ │ │ └── _manage_subscriptions.text.erb │ │ │ └── subscriptions │ │ │ └── index.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200823014211_add_shiny_lists_tables.rb │ │ │ └── 20201009124505_add_deleted_at_to_lists_and_subscriptions.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_lists.rb │ │ ├── shiny_lists │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_lists_tasks.rake │ ├── package.yml │ ├── shiny_lists.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_lists │ │ │ ├── lists.rb │ │ │ └── subscriptions.rb │ │ └── users.rb │ │ ├── helpers │ │ └── shiny_lists │ │ │ └── main_site_helper_spec.rb │ │ ├── models │ │ └── shiny_lists │ │ │ ├── list_spec.rb │ │ │ └── subscription_spec.rb │ │ └── requests │ │ └── shiny_lists │ │ ├── admin │ │ ├── lists_controller_spec.rb │ │ └── subscriptions_controller_spec.rb │ │ └── subscriptions_controller_spec.rb ├── ShinyNews │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_news │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_news │ │ │ │ ├── admin │ │ │ │ └── news_posts_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── news_controller.rb │ │ ├── helpers │ │ │ └── shiny_news │ │ │ │ └── main_site_helper.rb │ │ ├── jobs │ │ │ └── shiny_news │ │ │ │ ├── application_job.rb │ │ │ │ └── build_atom_feed_job.rb │ │ ├── models │ │ │ └── shiny_news │ │ │ │ ├── application_record.rb │ │ │ │ └── post.rb │ │ ├── policies │ │ │ └── shiny_news │ │ │ │ └── post_policy.rb │ │ └── views │ │ │ └── shiny_news │ │ │ ├── admin │ │ │ ├── news_posts │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── toolbar │ │ │ │ └── _section.html.erb │ │ │ └── user │ │ │ │ └── _edit_capabilities.html.erb │ │ │ ├── includes │ │ │ └── _head_part.html.erb │ │ │ ├── menu │ │ │ └── _section.html.erb │ │ │ ├── news │ │ │ ├── _right_sidebar_join.html.erb │ │ │ ├── _sidebar.html.erb │ │ │ ├── index.html.erb │ │ │ ├── index │ │ │ │ ├── _page_title.html.erb │ │ │ │ ├── _post_footer.html.erb │ │ │ │ └── _post_header.html.erb │ │ │ ├── month.html.erb │ │ │ ├── show.html.erb │ │ │ ├── show │ │ │ │ ├── _comment_form.html.erb │ │ │ │ ├── _discussion.html.erb │ │ │ │ ├── _footer_discussion_links.html.erb │ │ │ │ ├── _footer_votable_links.html.erb │ │ │ │ ├── _post_footer.html.erb │ │ │ │ ├── _post_header.html.erb │ │ │ │ └── _post_tags.html.erb │ │ │ └── year.html.erb │ │ │ ├── profile │ │ │ └── _content.html.erb │ │ │ └── search │ │ │ └── result │ │ │ └── shiny_news │ │ │ └── _post.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200806233918_create_shiny_news_posts.rb │ │ │ └── 20201008220226_add_deleted_at_to_news_post.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_news.rb │ │ ├── shiny_news │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_news_tasks.rake │ ├── package.yml │ ├── shiny_news.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_news │ │ │ └── news_posts.rb │ │ └── users.rb │ │ ├── jobs │ │ └── shiny_news │ │ │ └── build_atom_feed_job_spec.rb │ │ ├── models │ │ └── shiny_news │ │ │ └── post_spec.rb │ │ └── requests │ │ └── shiny_news │ │ ├── admin │ │ └── news_posts_controller_spec.rb │ │ └── news_controller_spec.rb ├── ShinyNewsletters │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_newsletters │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_newsletters │ │ │ │ ├── admin │ │ │ │ ├── editions │ │ │ │ │ └── elements_controller.rb │ │ │ │ ├── editions_controller.rb │ │ │ │ ├── sends_controller.rb │ │ │ │ ├── templates │ │ │ │ │ └── elements_controller.rb │ │ │ │ └── templates_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── newsletters_controller.rb │ │ ├── jobs │ │ │ └── shiny_newsletters │ │ │ │ ├── application_job.rb │ │ │ │ ├── send_to_list_job.rb │ │ │ │ └── send_to_subscriber_job.rb │ │ ├── mailers │ │ │ └── shiny_newsletters │ │ │ │ ├── application_mailer.rb │ │ │ │ └── newsletter_mailer.rb │ │ ├── models │ │ │ └── shiny_newsletters │ │ │ │ ├── application_record.rb │ │ │ │ ├── edition.rb │ │ │ │ ├── edition_element.rb │ │ │ │ ├── send.rb │ │ │ │ ├── template.rb │ │ │ │ └── template_element.rb │ │ ├── policies │ │ │ └── shiny_newsletters │ │ │ │ ├── edition_policy.rb │ │ │ │ ├── send_policy.rb │ │ │ │ └── template_policy.rb │ │ └── views │ │ │ └── shiny_newsletters │ │ │ ├── admin │ │ │ ├── editions │ │ │ │ ├── _element.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── sends │ │ │ │ ├── _scheduled.html.erb │ │ │ │ ├── _sending.html.erb │ │ │ │ ├── _sends.html.erb │ │ │ │ ├── _sent.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ ├── new.html.erb │ │ │ │ ├── sent.html.erb │ │ │ │ └── show.html.erb │ │ │ ├── templates │ │ │ │ ├── _element.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ └── user │ │ │ │ └── _edit_capabilities.html.erb │ │ │ ├── layouts │ │ │ ├── newsletter_mailer.html.mjml │ │ │ └── newsletter_mailer.text.erb │ │ │ └── newsletters │ │ │ ├── index.html.erb │ │ │ └── show.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200823235007_create_shiny_newsletters_tables.rb │ │ │ └── 20201009162923_add_deleted_at_to_newsletter_tables.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_newsletters.rb │ │ ├── shiny_newsletters │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ ├── shiny_newsletters_db.rake │ │ │ └── shiny_newsletters_sends.rake │ ├── package.yml │ ├── shiny_newsletters.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_newsletters │ │ │ ├── edition_elements.rb │ │ │ ├── editions.rb │ │ │ ├── sends.rb │ │ │ ├── template_elements.rb │ │ │ └── templates.rb │ │ └── users.rb │ │ ├── jobs │ │ └── shiny_newsletters │ │ │ ├── send_to_list_spec.rb │ │ │ └── send_to_subscriber_spec.rb │ │ ├── models │ │ └── shiny_newsletters │ │ │ ├── edition_element_spec.rb │ │ │ ├── edition_spec.rb │ │ │ ├── send_spec.rb │ │ │ ├── template_element_spec.rb │ │ │ └── template_spec.rb │ │ └── requests │ │ └── shiny_newsletters │ │ ├── admin │ │ ├── editions │ │ │ └── elements_controller_spec.rb │ │ ├── editions_controller_spec.rb │ │ ├── sends_controller_spec.rb │ │ ├── templates │ │ │ └── elements_controller_spec.rb │ │ └── templates_controller_spec.rb │ │ └── newsletters_controller_spec.rb ├── ShinyPages │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── components │ │ │ └── shiny_pages │ │ │ │ ├── admin │ │ │ │ └── menu │ │ │ │ │ ├── section_component.html.erb │ │ │ │ │ └── section_component.rb │ │ │ │ └── application_component.rb │ │ ├── controllers │ │ │ └── shiny_pages │ │ │ │ ├── admin │ │ │ │ ├── pages │ │ │ │ │ └── elements_controller.rb │ │ │ │ ├── pages_controller.rb │ │ │ │ ├── sections_controller.rb │ │ │ │ ├── templates │ │ │ │ │ └── elements_controller.rb │ │ │ │ └── templates_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── pages_controller.rb │ │ ├── helpers │ │ │ └── shiny_pages │ │ │ │ └── main_site_helper.rb │ │ ├── models │ │ │ └── shiny_pages │ │ │ │ ├── application_record.rb │ │ │ │ ├── page.rb │ │ │ │ ├── page_element.rb │ │ │ │ ├── section.rb │ │ │ │ ├── template.rb │ │ │ │ └── template_element.rb │ │ ├── policies │ │ │ └── shiny_pages │ │ │ │ ├── page_policy.rb │ │ │ │ ├── section_policy.rb │ │ │ │ └── template_policy.rb │ │ ├── public │ │ │ └── lib │ │ │ │ └── shiny_pages │ │ │ │ └── routes │ │ │ │ ├── root_page.rb │ │ │ │ └── top_level_pages.rb │ │ ├── validators │ │ │ └── shiny_pages │ │ │ │ └── top_level_slug_validator.rb │ │ └── views │ │ │ └── shiny_pages │ │ │ ├── admin │ │ │ ├── pages │ │ │ │ ├── _element.html.erb │ │ │ │ ├── _page_item.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── sections │ │ │ │ ├── edit.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── templates │ │ │ │ ├── _element.html.erb │ │ │ │ ├── edit.html.erb │ │ │ │ ├── index.html.erb │ │ │ │ └── new.html.erb │ │ │ ├── toolbar │ │ │ │ └── _section.html.erb │ │ │ └── user │ │ │ │ └── _edit_capabilities.html.erb │ │ │ └── menu │ │ │ └── _pages.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20200822131839_add_tables_for_shiny_pages.rb │ │ │ └── 20201009162910_add_deleted_at_to_page_tables.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_pages.rb │ │ ├── shiny_pages │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_pages_tasks.rake │ ├── package.yml │ ├── shiny_pages.gemspec │ └── spec │ │ ├── factories │ │ ├── shiny_pages │ │ │ ├── elements.rb │ │ │ ├── pages.rb │ │ │ ├── sections.rb │ │ │ ├── template_elements.rb │ │ │ └── templates.rb │ │ └── users.rb │ │ ├── models │ │ └── shiny_pages │ │ │ ├── page_element_spec.rb │ │ │ ├── page_spec.rb │ │ │ ├── section_spec.rb │ │ │ ├── template_element_spec.rb │ │ │ └── template_spec.rb │ │ └── requests │ │ └── shiny_pages │ │ ├── admin │ │ ├── pages │ │ │ └── elements_controller_spec.rb │ │ ├── pages_controller_spec.rb │ │ ├── sections_controller_spec.rb │ │ ├── templates │ │ │ └── elements_controller_spec.rb │ │ └── templates_controller_spec.rb │ │ └── pages_controller_spec.rb ├── ShinyProfiles │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── shiny_profiles │ │ │ │ ├── admin │ │ │ │ └── profiles_controller.rb │ │ │ │ ├── application_controller.rb │ │ │ │ └── profiles_controller.rb │ │ ├── helpers │ │ │ └── shiny_profiles │ │ │ │ └── main_site_helper.rb │ │ ├── models │ │ │ └── shiny_profiles │ │ │ │ ├── application_record.rb │ │ │ │ ├── link.rb │ │ │ │ └── profile.rb │ │ ├── policies │ │ │ └── shiny_profiles │ │ │ │ └── profile_policy.rb │ │ └── views │ │ │ └── shiny_profiles │ │ │ ├── admin │ │ │ └── profiles │ │ │ │ └── edit.html.erb │ │ │ ├── profiles │ │ │ ├── _admin.html.erb │ │ │ ├── _content.html.erb │ │ │ ├── _private.html.erb │ │ │ ├── _public.html.erb │ │ │ ├── edit.html.erb │ │ │ └── show.html.erb │ │ │ └── search │ │ │ └── result │ │ │ └── shiny_profiles │ │ │ └── _profile.html.erb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ └── routes.rb │ ├── db │ │ ├── migrate │ │ │ └── 20201128224232_create_shiny_profiles_tables.rb │ │ └── seeds.rb │ ├── lib │ │ ├── shiny_profiles.rb │ │ ├── shiny_profiles │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_profiles_tasks.rake │ ├── package.yml │ ├── shiny_profiles.gemspec │ └── spec │ │ ├── models │ │ └── shiny_profiles │ │ │ ├── link_spec.rb │ │ │ └── profile_spec.rb │ │ └── requests │ │ └── shiny_profiles │ │ ├── admin │ │ └── profiles_controller_spec.rb │ │ └── profiles_controller_spec.rb ├── ShinySEO │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── shiny_seo │ │ │ │ └── application_controller.rb │ │ ├── helpers │ │ │ └── shiny_seo │ │ │ │ └── application_helper.rb │ │ └── models │ │ │ └── shiny_seo │ │ │ ├── sitemap.rb │ │ │ └── sitemap_item.rb │ ├── bin │ │ └── rails │ ├── config │ │ ├── locales │ │ │ └── en.yml │ │ ├── routes.rb │ │ └── sitemap.rb │ ├── lib │ │ ├── shiny_seo.rb │ │ ├── shiny_seo │ │ │ ├── engine.rb │ │ │ └── version.rb │ │ └── tasks │ │ │ └── shiny_seo_tasks.rake │ ├── package.yml │ ├── shiny_seo.gemspec │ └── spec │ │ └── models │ │ └── shiny_seo │ │ └── sitemap_spec.rb └── ShinySearch │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ ├── assets │ │ ├── config │ │ │ └── shiny_search_manifest.js │ │ ├── images │ │ │ └── shiny_search │ │ │ │ ├── .keep │ │ │ │ └── algolia-logo.png │ │ └── stylesheets │ │ │ └── shiny_search │ │ │ ├── application.css │ │ │ └── shinycms.css │ ├── controllers │ │ └── shiny_search │ │ │ ├── application_controller.rb │ │ │ └── search_controller.rb │ ├── helpers │ │ └── shiny_search │ │ │ └── main_site_helper.rb │ ├── jobs │ │ └── shiny_search │ │ │ └── application_job.rb │ ├── public │ │ └── models │ │ │ └── concerns │ │ │ └── shiny_search │ │ │ └── searchable.rb │ └── views │ │ └── shiny_search │ │ └── search │ │ ├── _algolia_logo.html.erb │ │ ├── _form.html.erb │ │ ├── _new.html.erb │ │ ├── _no_results.html.erb │ │ ├── _results.html.erb │ │ └── index.html.erb │ ├── bin │ └── rails │ ├── config │ ├── initializers │ │ └── algoliasearch.rb │ ├── locales │ │ └── en.yml │ └── routes.rb │ ├── db │ └── seeds.rb │ ├── lib │ ├── shiny_search.rb │ ├── shiny_search │ │ ├── engine.rb │ │ └── version.rb │ └── tasks │ │ └── shiny_search_tasks.rake │ ├── package.yml │ ├── shiny_search.gemspec │ └── spec │ ├── helpers │ └── shiny_search │ │ └── main_site_helper_spec.rb │ └── requests │ └── shiny_search │ └── search_controller_spec.rb ├── public ├── 400.html ├── 404.html ├── 406-unsupported-browser.html ├── 422.html ├── 500.html ├── favicon.ico ├── feeds │ └── atom │ │ └── .keep ├── icon.png ├── icon.svg ├── images │ ├── ShinyCMS-logo.png │ ├── banner.png │ ├── bg01.jpg │ ├── bg02.jpg │ ├── bg03.jpg │ ├── blog.png │ ├── nested-comments.png │ ├── oval-spiral.png │ ├── pages.png │ ├── pic05.jpg │ ├── pic06.jpg │ ├── pic07.jpg │ ├── pic08.jpg │ ├── spam-comment-moderation.png │ └── spiral.png ├── js │ ├── ckeditor │ │ └── config.js │ ├── shinycms │ │ └── admin_area.js │ └── smartmenus │ │ └── jquery.smartmenus.min.js └── robots.txt ├── site └── .circleci │ └── config.yml ├── spec ├── factories │ └── ahoy_messages.rb ├── rails_helper.rb ├── requests │ └── ahoy_email_spec.rb └── spec_helper.rb ├── storage └── .keep ├── themes ├── coming_soon │ ├── images │ │ └── coming_soon │ │ │ ├── bg01.jpg │ │ │ ├── bg02.jpg │ │ │ └── bg03.jpg │ ├── stylesheets │ │ └── coming_soon │ │ │ ├── fontawesome-all.min.css │ │ │ ├── index.css │ │ │ └── main.css │ └── views │ │ ├── layouts │ │ └── main_site.html.erb │ │ └── pages │ │ └── templates │ │ └── index.html.erb ├── halcyonic │ ├── images │ │ └── halcyonic │ │ │ ├── bg01.jpg │ │ │ ├── bg02.jpg │ │ │ ├── bg03.jpg │ │ │ ├── bg04.jpg │ │ │ ├── bg04.png │ │ │ ├── button-big-active.svg │ │ │ ├── button-big-hover.svg │ │ │ ├── button-big.svg │ │ │ ├── icon-checkmark.png │ │ │ └── mobileUI-site-nav-opener-bg.svg │ ├── stylesheets │ │ └── halcyonic │ │ │ ├── index.css │ │ │ ├── main.scss │ │ │ └── shinycms.scss │ └── views │ │ ├── includes │ │ ├── _footer.html.erb │ │ ├── _footer_javascript.html.erb │ │ ├── _head.html.erb │ │ └── _header.html.erb │ │ ├── layouts │ │ └── main_site.html.erb │ │ ├── shiny_newsletters │ │ └── newsletter_mailer │ │ │ ├── an_example.html.mjml │ │ │ ├── an_example.text.erb │ │ │ ├── three_column_header.html.mjml │ │ │ └── three_column_header.text.erb │ │ └── shiny_pages │ │ └── pages │ │ ├── contact-form.html.erb │ │ ├── double-sidebar.html.erb │ │ ├── index.html.erb │ │ ├── left-sidebar.html.erb │ │ ├── no-sidebar.html.erb │ │ └── right-sidebar.html.erb └── javascript │ ├── coming_soon │ └── index.js │ └── halcyonic │ ├── breakpoints.min.js │ ├── browser.min.js │ ├── index.js │ ├── jquery.min.js │ ├── main.js │ └── util.js ├── tools ├── bundle-install ├── heroku-release ├── mutate ├── packwerk ├── parallel-rspec ├── parallel-rspec-create-databases ├── parallel-rspec-refresh-databases ├── rails-best-practices ├── sidekiq-dev └── tests │ ├── admin-area-requests │ ├── main-site-requests │ ├── models │ ├── one-or-two-of-each-type │ ├── requests │ └── root └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /.codebeatignore: -------------------------------------------------------------------------------- 1 | # Third-party JavaScript code in themes 2 | themes/javascript/ 3 | -------------------------------------------------------------------------------- /.flayignore: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2021 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Ignore duplication in controllers. The slimmer you keep your Rails controllers, 10 | # the more similar they're going to look! 'Conventional', one might say... 11 | 12 | plugins/Shiny*/app/controllers/shiny*/**/* 13 | 14 | # Pundit policies are even more similar; ignore them too. 15 | 16 | plugins/Shiny*/app/policies/shiny*/**/* 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: bundler 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | --require rspec/instafail 3 | --format RSpec::Instafail 4 | -------------------------------------------------------------------------------- /.rspec_parallel: -------------------------------------------------------------------------------- 1 | --format progress 2 | --format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log 3 | --format ParallelTests::RSpec::FailuresLogger --out tmp/failing_specs.log 4 | --format ParallelTests::RSpec::SummaryLogger --out tmp/spec_summary.log 5 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # ShinyCMS ~ https://shinycms.org 2 | # 3 | # Copyright 2009-2021 Denny de la Haye ~ https://denny.me 4 | # 5 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 6 | 7 | inherit_from: plugins/ShinyCMS/.rubocop.yml 8 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.3 2 | -------------------------------------------------------------------------------- /.rubycritic.yml: -------------------------------------------------------------------------------- 1 | no_browser: true 2 | threshold_score: 1 3 | paths: 4 | - plugins/ShinyCMS/app 5 | - app 6 | - lib/generators/shiny 7 | - plugins/ShinyAccess/app 8 | - plugins/ShinyBlog/app 9 | - plugins/ShinyForms/app 10 | - plugins/ShinyInserts/app 11 | - plugins/ShinyLists/app 12 | - plugins/ShinyNews/app 13 | - plugins/ShinyNewsletters/app 14 | - plugins/ShinyPages/app 15 | - plugins/ShinyProfiles/app 16 | - plugins/ShinySearch/app 17 | - plugins/ShinySEO/app 18 | -------------------------------------------------------------------------------- /.scss-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exclude: 3 | - themes/halcyonic/stylesheets/halcyonic/main.scss 4 | - node_modules/* 5 | - vendor/* 6 | linters: 7 | ImportantRule: 8 | enabled: false 9 | LeadingZero: 10 | enabled: false 11 | MergeableSelector: 12 | enabled: false 13 | Shorthand: 14 | enabled: false 15 | SpaceAfterPropertyColon: 16 | enabled: false 17 | SpaceBetweenParens: 18 | enabled: false 19 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | release: ./tools/heroku-release 2 | web: bundle exec rails s 3 | worker: bundle exec sidekiq 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake - for example 4 | # lib/tasks/capistrano.rake - and they will automatically be available to Rake. 5 | 6 | require_relative 'config/application' 7 | 8 | Rails.application.load_tasks 9 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link shinycms_manifest.js 2 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # :nocov: 10 | class ApplicationController < ActionController::Base 11 | def index 12 | render inline: 'Hello world.' 13 | end 14 | end 15 | # :nocov: 16 | -------------------------------------------------------------------------------- /app/models/ahoy/event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Model for tracking website events using ahoy 10 | class Ahoy::Event < ApplicationRecord 11 | include Ahoy::QueryMethods 12 | 13 | self.table_name = 'ahoy_events' 14 | 15 | belongs_to :visit 16 | belongs_to :user, optional: true 17 | end 18 | -------------------------------------------------------------------------------- /app/models/ahoy/message.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Model for tracking emails using ahoy 10 | class Ahoy::Message < ApplicationRecord 11 | self.table_name = 'ahoy_messages' 12 | 13 | belongs_to :user, polymorphic: true, optional: true 14 | end 15 | -------------------------------------------------------------------------------- /app/models/ahoy/visit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Model for tracking website visits using ahoy 10 | class Ahoy::Visit < ApplicationRecord 11 | self.table_name = 'ahoy_visits' 12 | 13 | has_many :events, dependent: :destroy, class_name: 'Ahoy::Event' 14 | belongs_to :user, optional: true, class_name: ShinyCMS.config_user_model 15 | end 16 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Base class for models 10 | class ApplicationRecord < ActiveRecord::Base 11 | self.abstract_class = true 12 | end 13 | -------------------------------------------------------------------------------- /bin/brakeman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | ARGV.unshift("--ensure-latest") 6 | 7 | load Gem.bin_path("brakeman", "brakeman") 8 | -------------------------------------------------------------------------------- /bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | exec "./bin/rails", "server", *ARGV 3 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | # explicit rubocop config increases performance slightly while avoiding config confusion. 6 | ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) 7 | 8 | load Gem.bin_path("rubocop", "rubocop") 9 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | Rails.application.load_server 9 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path( '../Gemfile', __dir__ ) 4 | 5 | # Set up gems listed in the Gemfile 6 | require 'bundler/setup' 7 | 8 | # Load bootsnap here if you're using it 9 | # require 'bootsnap/setup' 10 | -------------------------------------------------------------------------------- /config/coverband.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Pull Coverband config in from ShinyCMS core plugin 10 | 11 | require_relative '../plugins/ShinyCMS/config/coverband' 12 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative 'application' 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /config/initializers/acts_as_taggable_on.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | ActsAsTaggableOn.remove_unused_tags = true 10 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = '1.0' 7 | 8 | # Add additional assets to the asset load path. 9 | # Rails.application.config.assets.paths << Emoji.images_path 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w[ admin.js admin.css ] 15 | -------------------------------------------------------------------------------- /config/initializers/blazer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Pull Blazer config in from ShinyCMS core plugin 10 | 11 | require_relative '../../plugins/ShinyCMS/config/initializers/blazer' 12 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Specify a serializer for the signed and encrypted cookie jars. 6 | # Valid options are :json, :marshal, and :hybrid. 7 | Rails.application.config.action_dispatch.cookies_serializer = :json 8 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure sensitive parameters which will be filtered from the log file. 6 | Rails.application.config.filter_parameters += %i[ 7 | passw secret token _key crypt salt certificate otp ssn 8 | ] 9 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Define an application-wide HTTP permissions policy. For further 6 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy 7 | 8 | # Rails.application.config.permissions_policy do |policy| 9 | # policy.camera :none 10 | # policy.gyroscope :none 11 | # policy.microphone :none 12 | # policy.usb :none 13 | # policy.fullscreen :self 14 | # policy.payment :self, "https://secure.example.com" 15 | # end 16 | -------------------------------------------------------------------------------- /config/initializers/rails_email_preview.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Pull RailsEmailPreview config in from ShinyCMS core plugin 10 | 11 | require_relative '../../plugins/ShinyCMS/config/initializers/rails_email_preview' 12 | -------------------------------------------------------------------------------- /config/initializers/shinycms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # ShinyCMS.configure( 10 | # user_model: 'User' # Default: 'ShinyCMS::User' 11 | # ) 12 | 13 | # ShinyNewsletters.configure( 14 | # list_model: 'MyList' # Default: 'ShinyLists::List' 15 | # ) 16 | -------------------------------------------------------------------------------- /config/initializers/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # This version number is specifically for the ShinyHostApp 10 | 11 | # Each ShinyCMS plugin has its own version number 12 | # The core plugin is currently at version 21.06 13 | 14 | module ShinyHostApp 15 | VERSION = '21.06' 16 | public_constant :VERSION 17 | end 18 | -------------------------------------------------------------------------------- /db/archived-migrations/20191109152134_create_sessions.rb: -------------------------------------------------------------------------------- 1 | class CreateSessions < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :sessions, if_not_exists: true do |t| 4 | t.string :session_id, null: false 5 | t.text :data 6 | 7 | t.timestamps 8 | end 9 | 10 | add_index :sessions, :session_id, unique: true 11 | add_index :sessions, :updated_at 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/archived-migrations/20191127225110_create_feature_flags.rb: -------------------------------------------------------------------------------- 1 | class CreateFeatureFlags < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :feature_flags do |t| 4 | t.string :name, null: false 5 | t.text :description 6 | t.boolean :enabled, null: false, default: false 7 | t.boolean :enabled_for_logged_in, null: false, default: false 8 | t.boolean :enabled_for_admins, null: false, default: false 9 | 10 | t.timestamps 11 | end 12 | 13 | add_index :feature_flags, :name, unique: true 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/archived-migrations/20191206184800_create_capability_categories.rb: -------------------------------------------------------------------------------- 1 | class CreateCapabilityCategories < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :capability_categories do |t| 4 | t.string :name, null: false 5 | 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/archived-migrations/20191206184808_create_capabilities.rb: -------------------------------------------------------------------------------- 1 | class CreateCapabilities < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :capabilities do |t| 4 | t.string :name, null: false 5 | t.integer :category_id 6 | t.string :description 7 | 8 | t.timestamps 9 | end 10 | 11 | add_foreign_key :capabilities, :capability_categories, column: :category_id 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/archived-migrations/20191206184835_create_user_capabilities.rb: -------------------------------------------------------------------------------- 1 | class CreateUserCapabilities < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :user_capabilities do |t| 4 | t.integer :user_id, null: false 5 | t.integer :capability_id, null: false 6 | 7 | t.timestamps 8 | end 9 | 10 | add_foreign_key :user_capabilities, :users 11 | add_foreign_key :user_capabilities, :capabilities 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/archived-migrations/20191217175907_add_index_to_user_capabilities.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToUserCapabilities < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :user_capabilities, [ :user_id, :capability_id ], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200203230336_drop_settings.rb: -------------------------------------------------------------------------------- 1 | class DropSettings < ActiveRecord::Migration[6.0] 2 | def change 3 | drop_table :settings, if_exists: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200203231532_create_settings.rb: -------------------------------------------------------------------------------- 1 | class CreateSettings < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :settings do |t| 4 | t.string :name, null: false 5 | t.string :description 6 | 7 | t.string :level, null: false, default: 'site' 8 | t.boolean :locked, null: false, default: true 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/archived-migrations/20200205211726_create_setting_values.rb: -------------------------------------------------------------------------------- 1 | class CreateSettingValues < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :setting_values do |t| 4 | t.integer :setting_id, null: false 5 | t.integer :user_id 6 | t.string :value 7 | 8 | t.timestamps 9 | end 10 | 11 | add_foreign_key :setting_values, :settings, column: :setting_id 12 | add_foreign_key :setting_values, :users, column: :user_id 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/archived-migrations/20200218155447_add_discussions.rb: -------------------------------------------------------------------------------- 1 | class AddDiscussions < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :discussions, if_not_exists: true do |t| 4 | t.references :resource, polymorphic: true 5 | 6 | t.boolean :locked, null: false, default: false 7 | t.boolean :hidden, null: false, default: false 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/archived-migrations/20200227220410_rename_author_id_to_user_id_in_comments.rb: -------------------------------------------------------------------------------- 1 | class RenameAuthorIdToUserIdInComments < ActiveRecord::Migration[6.0] 2 | def change 3 | rename_column :comments, :author_id, :user_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200302203545_add_ip_address_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddIpAddressToComments < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :comments, :ip_address, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200310005145_create_email_recipients.rb: -------------------------------------------------------------------------------- 1 | class CreateEmailRecipients < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :email_recipients do |t| 4 | t.string :name, null: false 5 | t.string :email, null: false 6 | t.string :canonical_email, null: false 7 | t.uuid :token, null: false 8 | 9 | t.timestamps 10 | end 11 | add_index :email_recipients, :email, unique: true 12 | add_index :email_recipients, :token, unique: true 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/archived-migrations/20200324174621_add_unique_index_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToComments < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :comments, [:number, :discussion_id], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200324174637_add_unique_index_to_setting_values.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToSettingValues < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :setting_values, [:setting_id, :user_id], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200326020927_add_canonical_email_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddCanonicalEmailToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :canonical_email, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/archived-migrations/20200327000512_create_consents.rb: -------------------------------------------------------------------------------- 1 | class CreateConsents < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :consents do |t| 4 | t.string :purpose_type, null: false 5 | t.integer :purpose_id, null: false 6 | 7 | t.string :action, null: false 8 | t.text :wording, null: false 9 | t.string :url 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/archived-migrations/20200327014155_create_do_not_contacts.rb: -------------------------------------------------------------------------------- 1 | class CreateDoNotContacts < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :do_not_contacts do |t| 4 | t.string :email 5 | 6 | t.timestamps 7 | end 8 | add_index :do_not_contacts, :email, unique: true 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/archived-migrations/20200409180906_create_ahoy_messages.rb: -------------------------------------------------------------------------------- 1 | class CreateAhoyMessages < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :ahoy_messages do |t| 4 | t.references :user, polymorphic: true 5 | t.text :to 6 | t.string :mailer 7 | t.text :subject 8 | t.string :token 9 | t.timestamp :sent_at 10 | t.timestamp :opened_at 11 | t.timestamp :clicked_at 12 | end 13 | add_index :ahoy_messages, :token 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/archived-migrations/20200422183132_create_pg_search_documents.rb: -------------------------------------------------------------------------------- 1 | class CreatePgSearchDocuments < ActiveRecord::Migration[6.0] 2 | def self.up 3 | say_with_time("Creating table for pg_search multisearch") do 4 | create_table :pg_search_documents do |t| 5 | t.text :content 6 | t.belongs_to :searchable, polymorphic: true, index: true 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | 12 | def self.down 13 | say_with_time("Dropping table for pg_search multisearch") do 14 | drop_table :pg_search_documents 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/archived-migrations/20200702204022_create_votable_ips.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateVotableIps < ActiveRecord::Migration[6.0] 4 | def change 5 | create_table :votable_ips do |t| 6 | t.string :ip_address, null: false 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/archived-migrations/20200724210954_drop_unused_foreign_keys.rb: -------------------------------------------------------------------------------- 1 | class DropUnusedForeignKeys < ActiveRecord::Migration[6.0] 2 | def change 3 | remove_column :blog_posts, :discussion_id 4 | remove_column :news_posts, :discussion_id 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20200813090405_change_display_name_to_public_name.rb: -------------------------------------------------------------------------------- 1 | class ChangeDisplayNameToPublicName < ActiveRecord::Migration[6.0] 2 | def change 3 | rename_column :users, :display_name, :public_name 4 | rename_column :users, :display_email, :public_email 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20200905192113_create_consent_versions.rb: -------------------------------------------------------------------------------- 1 | class CreateConsentVersions < ActiveRecord::Migration[6.0] 2 | def change 3 | drop_table :consents, if_exists: true 4 | 5 | create_table :consent_versions do |t| 6 | t.string :name, null: false 7 | t.string :slug, null: false 8 | t.text :display_text, null: false 9 | t.text :admin_notes 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/archived-migrations/20201004134541_create_comment_authors.rb: -------------------------------------------------------------------------------- 1 | class CreateCommentAuthors < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :comment_authors do |t| 4 | t.string :name, null: false 5 | t.string :website 6 | t.inet :ip_address, null: false 7 | t.uuid :token, null: false 8 | 9 | t.references :email_recipient, null: true 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/archived-migrations/20201007212946_add_deleted_at_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToUser < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :deleted_at, :timestamp 4 | add_index :users, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008220616_add_deleted_at_to_blog_post.shiny_blog.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_blog (originally 20201008220226) 2 | class AddDeletedAtToBlogPost < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_blog_posts, :deleted_at, :timestamp 5 | add_index :shiny_blog_posts, :deleted_at 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008220622_add_deleted_at_to_news_post.shiny_news.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_news (originally 20201008220226) 2 | class AddDeletedAtToNewsPost < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_news_posts, :deleted_at, :timestamp 5 | add_index :shiny_news_posts, :deleted_at 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008233537_add_deleted_at_to_discussion.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToDiscussion < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :discussions, :deleted_at, :timestamp 4 | add_index :discussions, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008233543_add_deleted_at_to_comment.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToComment < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :comments, :deleted_at, :timestamp 4 | add_index :comments, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008234150_add_deleted_at_to_comment_author.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToCommentAuthor < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :comment_authors, :deleted_at, :timestamp 4 | add_index :comment_authors, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008234156_add_deleted_at_to_consent_version.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToConsentVersion < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :consent_versions, :deleted_at, :timestamp 4 | add_index :consent_versions, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008234205_add_deleted_at_to_do_not_contact.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToDoNotContact < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :do_not_contacts, :deleted_at, :timestamp 4 | add_index :do_not_contacts, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008234213_add_deleted_at_to_feature_flag.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToFeatureFlag < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :feature_flags, :deleted_at, :timestamp 4 | add_index :feature_flags, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201008235031_add_deleted_at_to_email_recipient.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToEmailRecipient < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :email_recipients, :deleted_at, :timestamp 4 | add_index :email_recipients, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009125021_add_deleted_at_to_forms.shiny_forms.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_forms (originally 20201009124440) 2 | class AddDeletedAtToForms < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_forms_forms, :deleted_at, :timestamp 5 | add_index :shiny_forms_forms, :deleted_at 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009125026_add_deleted_at_to_lists_and_subscriptions.shiny_lists.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_lists (originally 20201009124505) 2 | class AddDeletedAtToListsAndSubscriptions < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_lists_lists, :deleted_at, :timestamp 5 | add_column :shiny_lists_subscriptions, :deleted_at, :timestamp 6 | add_index :shiny_lists_lists, :deleted_at 7 | add_index :shiny_lists_subscriptions, :deleted_at 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009125033_add_deleted_at_to_insert_sets_and_elements.shiny_inserts.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_inserts (originally 20201009124530) 2 | class AddDeletedAtToInsertSetsAndElements < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_inserts_sets, :deleted_at, :timestamp 5 | add_column :shiny_inserts_elements, :deleted_at, :timestamp 6 | add_index :shiny_inserts_sets, :deleted_at 7 | add_index :shiny_inserts_elements, :deleted_at 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009144825_add_deleted_at_to_capabilities.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToCapabilities < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :capability_categories, :deleted_at, :timestamp 4 | add_column :capabilities, :deleted_at, :timestamp 5 | add_index :capability_categories, :deleted_at 6 | add_index :capabilities, :deleted_at 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009144833_add_deleted_at_to_settings.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToSettings < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :settings, :deleted_at, :timestamp 4 | add_column :setting_values, :deleted_at, :timestamp 5 | add_index :settings, :deleted_at 6 | add_index :setting_values, :deleted_at 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/archived-migrations/20201009164412_add_deleted_at_to_user_capabilities.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToUserCapabilities < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :user_capabilities, :deleted_at, :timestamp 4 | add_index :user_capabilities, :deleted_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/archived-migrations/20201031050440_add_bot_protection_booleans_to_forms.shiny_forms.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_forms (originally 20201031050301) 2 | class AddBotProtectionBooleansToForms < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :shiny_forms_forms, :use_recaptcha, :boolean, default: true 5 | add_column :shiny_forms_forms, :use_akismet, :boolean, default: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/archived-migrations/20201206144100_add_missing_indexes.rb: -------------------------------------------------------------------------------- 1 | class AddMissingIndexes < ActiveRecord::Migration[6.0] 2 | def change 3 | add_index :capabilities, :category_id 4 | add_index :comments, :parent_id 5 | 6 | add_index :shiny_pages_sections, :default_page_id 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20210226024355_rename_comment_authors.shiny_cms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # This migration comes from shiny_cms (originally 20210226020652) 3 | 4 | # ShinyCMS ~ https://shinycms.org 5 | # 6 | # Copyright 2009-2021 Denny de la Haye ~ https://denny.me 7 | # 8 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 9 | 10 | class RenameCommentAuthors < ActiveRecord::Migration[6.1] 11 | def change 12 | rename_table :shinycms_comment_authors, :shinycms_pseudonymous_authors 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20210226051341_create_shinycms_anonymous_authors.shiny_cms.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from shiny_cms (originally 20210226050046) 2 | class CreateShinyCMSAnonymousAuthors < ActiveRecord::Migration[6.1] 3 | def change 4 | create_table :shinycms_anonymous_authors 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20210226060425_rename_website_column.shiny_cms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # This migration comes from shiny_cms (originally 20210226060005) 3 | 4 | # ShinyCMS ~ https://shinycms.org 5 | # 6 | # Copyright 2009-2021 Denny de la Haye ~ https://denny.me 7 | # 8 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 9 | 10 | class RenameWebsiteColumn < ActiveRecord::Migration[6.1] 11 | def change 12 | rename_column :shinycms_pseudonymous_authors, :website, :url 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20241106184645_index_ahoy_visits.shiny_cms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # This migration comes from shiny_cms (originally 20241106060001) 3 | 4 | # ShinyCMS ~ https://shinycms.org 5 | # 6 | # Copyright 2009-2024 Denny de la Haye ~ https://denny.me 7 | # 8 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 9 | 10 | class IndexAhoyVisits < ActiveRecord::Migration[6.1] 11 | def add 12 | add_index :ahoy_visits, [ :visitor_token, :started_at ] 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20250206162503_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20211119233751) 2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] 3 | def change 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | change_column_null(:active_storage_blobs, :checksum, true) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # This file is invoked when the database is created with `rails db:setup` or reset 10 | # with `rails db:reset`. You can reload this data at any time using `rails db:seed`. 11 | 12 | # Hand over to the seed task in the ShinyCMS core plugin 13 | Rake::Task[ 'shinycms:db:seed' ].invoke 14 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.shinycms.org -------------------------------------------------------------------------------- /docs/Developers/Notes/menu-icons.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Developer Notes 2 | 3 | ## Admin area menu icons 4 | 5 | All of the icons I've used in the admin-area sidebar menu (and a few other places in the admin area) are part of the free icon set from CoreUI. If you're adding a new feature (or want to change the icon for an existing one) you can look here to see what's available: https://coreui.io/icons/free 6 | -------------------------------------------------------------------------------- /docs/Developers/Notes/needs-indexing.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Developer Notes 2 | 3 | Ruby console snippet to find database tables that need indexes... 4 | 5 | ```ruby 6 | c = ActiveRecord::Base.connection 7 | 8 | c.tables.collect do |t| 9 | columns = c.columns(t).collect(&:name).select {|x| x.ends_with?("_id" || x.ends_with("_type"))} 10 | indexed_columns = c.indexes(t).collect(&:columns).flatten.uniq 11 | unindexed = columns - indexed_columns 12 | unless unindexed.empty? 13 | puts "#{t}: #{unindexed.join(", ")}" 14 | end 15 | end 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/Developers/rake-tasks.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Developer Documentation 2 | 3 | ## Rake tasks 4 | 5 | ShinyCMS includes some rake tasks which are probably only useful to people developing new CMS features. 6 | 7 | ### Demo site data 8 | 9 | ``` 10 | rails shinycms:demo:export # ShinyCMS: export current database content into db/demo_site_data.rb 11 | ``` 12 | 13 | This export task is useful if you are a developer who is adding a new feature to ShinyCMS, and you want to add some demo data for that new feature, to make it easier for people to try it out. 14 | -------------------------------------------------------------------------------- /docs/Features/MainApp/Charts.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Charts and Dashboards 4 | 5 | ShinyCMS has [Blazer](https://github.com/ankane/blazer#readme) built-in, so that you can build your own custom queries, charts, and dashboards. 6 | 7 | ### Demo content 8 | 9 | Currently there is not a default or demo dashboard (but it is on the [TODO](../../Developers/TODO.md) list). 10 | 11 | 12 | #### Plugin status 13 | 14 | This feature is likely to be moved into a plugin at some point. 15 | -------------------------------------------------------------------------------- /docs/Features/MainApp/FeatureFlags.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Feature Flags 4 | 5 | Quickly and easily enable or disable CMS features (e.g. 'new user registrations') in the admin area. 6 | 7 | 8 | ### Rake task 9 | 10 | Feature flags can be checked and controlled on the command line too, via a rake task: 11 | ``` 12 | rails shiny:features:list 13 | rails shiny:feature:off[user_registrations] 14 | ``` 15 | 16 | 17 | #### Plugin status 18 | 19 | This feature would be the very last one to be converted into a plugin - after [User Accounts](UserAccounts.md) and [Site Settings](SiteSettings.md). 20 | -------------------------------------------------------------------------------- /docs/Features/MainApp/SiteSettings.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Site Settings 4 | 5 | Change most site settings from within the CMS admin area (e.g. 'allow anonymous comments') 6 | 7 | Allows you to specify which settings can be overridden by users - e.g. site_theme 8 | 9 | 10 | #### Plugin status 11 | 12 | This feature would be second from last to be converted into a plugin - after [User Accounts](UserAccounts.md) but before [Feature Flags](FeatureFlags.md). 13 | -------------------------------------------------------------------------------- /docs/Features/MainApp/Tags.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Tags 4 | 5 | The tag features are powered by [acts-as-taggable-on](https://github.com/mbleigh/acts-as-taggable-on#readme) 6 | 7 | 8 | #### Plugin status 9 | 10 | This feature will probably be moved into a plugin at some point. 11 | -------------------------------------------------------------------------------- /docs/Features/MainApp/Upvotes.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Upvotes 4 | 5 | (AKA 'likes', '+1', etc) 6 | 7 | The upvote features are powered by [ActsAsVotable](https://github.com/ryanto/acts_as_votable#readme). 8 | 9 | The gem also offers downvotes; ShinyCMS has separate settings to turn on just the upvote feature, or both upvotes and downvotes. 10 | 11 | ( TODO: should be a feature flag to turn on/off the whole voteable feature-set, and then a setting for 'allow_downvotes' ) 12 | 13 | 14 | #### Plugin status 15 | 16 | This feature will probably be moved into a plugin at some point. 17 | -------------------------------------------------------------------------------- /docs/Features/MainApp/WebStats.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Features 2 | 3 | ## Web stats 4 | 5 | Recording of web traffic stats is built-in, using [Ahoy](https://github.com/ankane/ahoy_email#readme) to gather the data. 6 | 7 | By default these features are disabled for privacy reasons. You can enable them on the Site Settings page in the admin area. 8 | 9 | There are also some additional settings to enable/disable some [GDPR/privacy-related features](https://github.com/ankane/ahoy#gdpr-compliance-1) offered by Ahoy. 10 | 11 | 12 | #### Plugin status 13 | 14 | This feature is likely to be moved into a plugin at some point. 15 | -------------------------------------------------------------------------------- /docs/Features/Plugins/ShinyForms.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Plugins 2 | 3 | ## ShinyForms 4 | 5 | This plugin provides some basic form handlers, allowing you to do things like 'send form content to site admin' when a form is submitted (useful for contact forms, order enquiries, etc). 6 | -------------------------------------------------------------------------------- /docs/Features/Plugins/ShinyInserts.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Plugins 2 | 3 | ## ShinyInserts 4 | 5 | Reusable content fragments for inclusion in any template in any section of the main site 6 | 7 | 8 | ### Admin page 9 | 10 | 11 | ### Template tag 12 | 13 | <%= insert( :name_of_insert ) %> 14 | -------------------------------------------------------------------------------- /docs/Features/Plugins/ShinyLists.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Plugins 2 | 3 | ## ShinyLists 4 | 5 | This plugin provides mailing list features (broadcast, not discussion). It is intended to be paired with ShinyNewsletters, for sending promotional emails. 6 | 7 | * Double opt-in 8 | * Stores details of exact consent given (GDPR) 9 | * Allows users to manage their subscriptions online 10 | * Identifies people without user accounts using a unique token included in their links 11 | * Permanent 'do not contact' option 12 | -------------------------------------------------------------------------------- /docs/create-blazer-db-user.sql: -------------------------------------------------------------------------------- 1 | begin; 2 | create role blazer login password 'YOUR-PASSWORD-HERE'; 3 | grant connect on database shinycms_development to blazer; 4 | grant usage on schema public to blazer; 5 | grant select on all tables in schema public to blazer; 6 | alter default privileges in schema public grant select on tables to blazer; 7 | commit; 8 | -------------------------------------------------------------------------------- /docs/tldr.md: -------------------------------------------------------------------------------- 1 | # ShinyCMS Documentation 2 | 3 | ## Installation: the tl,dr version 4 | 5 | ```bash 6 | git clone https://github.com/denny/ShinyCMS-ruby 7 | cd ShinyCMS-ruby 8 | cp docs/env.sample .env.development.local 9 | # Edit .env.development.local in case you want/need to change anything 10 | bundle install 11 | yarn install 12 | rails db:setup 13 | rails shiny:demo:load # if you want the demo data loaded 14 | rails shiny:admin:create # if you didn't load the demo data 15 | rails s 16 | ``` 17 | 18 | You should now have a ShinyCMS site at http://localhost:3000, with an admin area at http://localhost:3000/admin 19 | -------------------------------------------------------------------------------- /lib/generators/shiny/plugin/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | The command 'rails g shiny:plugin plugins/[name]' creates a skeleton for developing a ShinyCMS plugin 3 | 4 | Example: 5 | cd ShinyCMS-ruby 6 | rails g shiny:plugin plugins/ShinyThing 7 | 8 | This generates a skeletal ShinyCMS plugin in ShinyCMS-ruby/plugins/ShinyThing 9 | 10 | Please read ShinyCMS-ruby/docs/Developers/Plugins.md for more information 11 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' do 4 | gemspec 5 | end 6 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/controllers/%namespaced_name%/admin_controller.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base controller for #{camelized_modules} admin features 5 | # Inherits from ShinyCMS AdminController 6 | class AdminController < ::AdminController 7 | helper Rails.application.routes.url_helpers 8 | end 9 | rb 10 | %> 11 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/controllers/%namespaced_name%/application_controller.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base controller for the #{camelized_modules} plugin for ShinyCMS (see also MainController, AdminController) 5 | class ApplicationController < ActionController::Base 6 | end 7 | rb 8 | %> 9 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/controllers/%namespaced_name%/main_controller.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base controller for #{camelized_modules} main site features 5 | # Inherits from ShinyCMS MainController 6 | class MainController < ::MainController 7 | helper Rails.application.routes.url_helpers 8 | end 9 | rb 10 | %> 11 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/helpers/%namespaced_name%/application_helper.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base helper for #{camelized_modules} 5 | module ApplicationHelper 6 | end 7 | rb 8 | %> 9 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/jobs/%namespaced_name%/application_job.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | class ApplicationJob < ActiveJob::Base 5 | end 6 | rb 7 | %> 8 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/mailers/%namespaced_name%/application_mailer.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base mailer for #{camelized_modules} 5 | class ApplicationMailer < ShinyCMS::BaseMailer 6 | def check_feature_flags 7 | stop! 8 | end 9 | 10 | def check_ok_to_email 11 | stop! 12 | end 13 | end 14 | rb 15 | %> 16 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/app/models/%namespaced_name%/application_record.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | # Base model class for #{camelized_modules} 5 | class ApplicationRecord < ActiveRecord::Base 6 | self.abstract_class = true 7 | def url_helpers 8 | #{camelized_modules}::Engine.routes.url_helpers 9 | end 10 | end 11 | rb 12 | %> 13 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/config/locales/en.yml.tt: -------------------------------------------------------------------------------- 1 | en: 2 | feature_flags: 3 | <%= name %>: <%= camelized_modules %> 4 | 5 | <%= name %>: 6 | admin: 7 | title: <%= camelized_modules %> 8 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/config/routes.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= camelized_modules %>::Engine.routes.draw do 4 | scope format: false do 5 | # ... 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/gitignore.tt: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | log/*.log 3 | pkg/ 4 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/lib/%namespaced_name%.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require '<%= namespaced_name %>/engine' 4 | 5 | # Namespace wrapper 6 | <%= wrap_in_modules '' %> 7 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/lib/%namespaced_name%/version.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <%= wrap_in_modules <<~rb 4 | VERSION = '#{Time.zone.now.year.to_s[-2,2]}.#{Time.zone.now.month}' 5 | public_constant :VERSION 6 | rb 7 | %> 8 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/rails/boot.rb.tt: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) 6 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/rails/engine_manifest.js.tt: -------------------------------------------------------------------------------- 1 | <% if !options.skip_javascript -%> 2 | //= link_directory ../javascripts/<%= namespaced_name %> .js 3 | <% end -%> 4 | //= link_directory ../stylesheets/<%= namespaced_name %> .css 5 | -------------------------------------------------------------------------------- /lib/templates/shiny/plugin/rails/routes.rb.tt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denny/ShinyCMS-ruby/09627797f3fdbf8ce943c08ae437bcb24413efe7/lib/templates/shiny/plugin/rails/routes.rb.tt -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denny/ShinyCMS-ruby/09627797f3fdbf8ce943c08ae437bcb24413efe7/log/.keep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shinycms", 3 | "author": "Denny de la Haye (denny.me)", 4 | "private": true, 5 | "dependencies": { 6 | "@rails/activestorage": "^6.1.710", 7 | "@rails/ujs": "^6.1.710", 8 | "acorn": "^8.15.0", 9 | "core-js": "^3.43.0", 10 | "is-svg": "^6.0.0", 11 | "jquery": "^3.6.0", 12 | "jquery-ui": "^1.14.1", 13 | "minimist": "^1.2.8", 14 | "mjml": "^4.15.3", 15 | "smartmenus": "^1.2.1", 16 | "yarn": "^1.22.22" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' do 4 | gemspec 5 | end 6 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/app/components/shiny_access/application_component.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyAccess 10 | # Base class for view components - part of the ShinyAccess plugin for ShinyCMS 11 | class ApplicationComponent < ViewComponent::Base 12 | include ShinyCMS::ViewComponentBase 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/app/controllers/shiny_access/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyAccess 10 | class ApplicationController < ActionController::Base; end 11 | end 12 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/app/jobs/shiny_access/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyAccess 10 | # Base job class for ShinyAccess 11 | class ApplicationJob < ActiveJob::Base 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/app/mailers/shiny_access/application_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyAccess 10 | class ApplicationMailer < ShinyCMS::BaseMailer; end 11 | end 12 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/app/models/shiny_access/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyAccess 10 | # Base model class for ShinyAccess 11 | class ApplicationRecord < ActiveRecord::Base 12 | self.abstract_class = true 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # This command will automatically be run when you run "rails" with Rails gems 5 | # installed from the root of your application. 6 | 7 | ENGINE_ROOT = File.expand_path( '..', __dir__ ) 8 | ENGINE_PATH = File.expand_path( '../lib/shiny_access/engine', __dir__ ) 9 | 10 | # Set up gems listed in the Gemfile. 11 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path( '../Gemfile', __dir__ ) 12 | require 'bundler/setup' if File.exist?( ENV['BUNDLE_GEMFILE'] ) 13 | 14 | require 'rails/all' 15 | require 'rails/engine/commands' 16 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/lib/shiny_access.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | require 'shiny_access/engine' 10 | 11 | # Namespace wrapper 12 | module ShinyAccess 13 | end 14 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/lib/shiny_access/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Version number ('Ubuntu style'; year and month) 10 | module ShinyAccess 11 | VERSION = '21.06' 12 | public_constant :VERSION 13 | end 14 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/package.yml: -------------------------------------------------------------------------------- 1 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 2 | # 3 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 4 | # 5 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 6 | 7 | # Packwerk config for this plugin 8 | 9 | enforce_dependencies: true 10 | 11 | enforce_privacy: true 12 | 13 | dependencies: 14 | - plugins/ShinyCMS 15 | -------------------------------------------------------------------------------- /plugins/ShinyAccess/spec/factories/shiny_access/groups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyAccess plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | # Factory for access control groups 10 | module ShinyAccess 11 | FactoryBot.define do 12 | factory :access_group, class: Group do 13 | internal_name { Faker::Books::CultureSeries.unique.culture_ship } 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' do 4 | gemspec 5 | end 6 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/components/shiny_blog/application_component.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyBlog plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyBlog 10 | # Base class for view components - part of the ShinyBlog plugin for ShinyCMS 11 | class ApplicationComponent < ViewComponent::Base 12 | include ShinyCMS::ViewComponentBase 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/controllers/shiny_blog/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyBlog plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyBlog 10 | class ApplicationController < ActionController::Base; end 11 | end 12 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/jobs/shiny_blog/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyBlog plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyBlog 10 | # Base job class - part of the ShinyBlog plugin for ShinyCMS 11 | class ApplicationJob < ActiveJob::Base 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/models/shiny_blog/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ShinyBlog plugin for ShinyCMS ~ https://shinycms.org 4 | # 5 | # Copyright 2009-2025 Denny de la Haye ~ https://denny.me 6 | # 7 | # ShinyCMS is free software; you can redistribute it and/or modify it under the terms of the GPL (version 2 or later) 8 | 9 | module ShinyBlog 10 | # Base model class for ShinyBlog plugin for ShinyCMS 11 | class ApplicationRecord < ActiveRecord::Base 12 | self.abstract_class = true 13 | 14 | def url_helpers 15 | Engine.routes.url_helpers 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/views/shiny_blog/admin/toolbar/_section.html.erb: -------------------------------------------------------------------------------- 1 | <% if plugin_name == 'ShinyBlog' && current_user_can?( :list, :blog_posts ) %> 2 | <%= t( 'shiny_blog.admin.blog_posts.toolbar' ) %>: 3 | <%= link_to t( 'list' ), shiny_blog.blog_posts_path %> 4 | <% if current_user_can? :add, :blog_posts %> 5 | / <%= link_to t( 'add' ), shiny_blog.new_blog_post_path %> 6 | <% end %> 7 | <% if current_user_can?( :edit, :blog_posts ) && @post.present? %> 8 | / <%= link_to t( 'edit' ), shiny_blog.edit_blog_post_path( @post ) %> 9 | <% end %> 10 | | 11 | <% end %> 12 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/views/shiny_blog/admin/user/_edit_capabilities.html.erb: -------------------------------------------------------------------------------- 1 | <% category_capabilities = %w[ list add edit destroy change_author ] %> 2 | <% category = capability_category( :blog_posts ) %> 3 | <%= render_capability_category( f, category, category_capabilities, show ) %> 4 | -------------------------------------------------------------------------------- /plugins/ShinyBlog/app/views/shiny_blog/blog/_right_sidebar_join.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
2 |