├── .circleci └── config.yml ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .gitlab-ci.yml ├── .rubocop.yml ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Rakefile ├── SECURITY.md ├── app ├── assets │ ├── images │ │ ├── .keep │ │ ├── christianity.png │ │ ├── codegolf.png │ │ ├── codidact.png │ │ ├── cooking.png │ │ ├── electrical.png │ │ ├── fbm.ico │ │ ├── judaism.png │ │ ├── languages-mobile.png │ │ ├── languages.png │ │ ├── logo-photo.png │ │ ├── logo-writing.png │ │ ├── logo.png │ │ ├── math.png │ │ ├── meta-logo.png │ │ ├── meta-mobile.png │ │ ├── meta.png │ │ ├── outdoors.png │ │ ├── software-full.png │ │ ├── software-mobile.png │ │ ├── specsci.png │ │ └── square.ico │ ├── imgfonts │ │ ├── LICENSE.txt │ │ ├── Roboto-Black-FRLHebrew.ttf │ │ ├── Roboto-Black.ttf │ │ ├── Roboto-BlackItalic.ttf │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-BoldItalic.ttf │ │ ├── Roboto-Italic.ttf │ │ ├── Roboto-Light.ttf │ │ ├── Roboto-LightItalic.ttf │ │ ├── Roboto-Medium.ttf │ │ ├── Roboto-MediumItalic.ttf │ │ ├── Roboto-Regular.ttf │ │ ├── Roboto-Thin.ttf │ │ └── Roboto-ThinItalic.ttf │ ├── javascripts │ │ ├── abilities.coffee │ │ ├── advertisement.js │ │ ├── application.js │ │ ├── birthday.coffee │ │ ├── categories.js │ │ ├── character_count.js │ │ ├── comments.js │ │ ├── keyboard_tools.js │ │ ├── licenses.js │ │ ├── livestamp.min.js │ │ ├── markdown.js │ │ ├── mod_warning.js │ │ ├── modals.js │ │ ├── moderator.js │ │ ├── notifications.js │ │ ├── pinned_links.coffee │ │ ├── posts.js │ │ ├── privileges.js │ │ ├── qpixel_api.js │ │ ├── site_settings.js │ │ ├── subscriptions.js │ │ ├── suggested_edit.js │ │ ├── tag_sets.js │ │ ├── tags.js │ │ ├── tour.js │ │ ├── users.js │ │ └── votes.js │ └── stylesheets │ │ ├── _variables.scss │ │ ├── abilities.scss │ │ ├── advertisement.scss │ │ ├── application.scss │ │ ├── articles.scss │ │ ├── birthday.scss │ │ ├── categories.scss │ │ ├── close_reasons.scss │ │ ├── comments.scss │ │ ├── errors.scss │ │ ├── forms.scss │ │ ├── keyboard_tools.scss │ │ ├── licenses.scss │ │ ├── markdown_tools.scss │ │ ├── mod_warning.scss │ │ ├── notifications.scss │ │ ├── pinned_links.scss │ │ ├── post_history.scss │ │ ├── posts.scss │ │ ├── reports.scss │ │ ├── site_settings.scss │ │ ├── subscriptions.scss │ │ ├── suggested_edit.scss │ │ ├── tabs.scss │ │ ├── tag_sets.scss │ │ ├── tags.scss │ │ ├── tour.scss │ │ ├── two_factor.scss │ │ ├── users.scss │ │ └── utilities.scss ├── controllers │ ├── abilities_controller.rb │ ├── admin_controller.rb │ ├── advertisement_controller.rb │ ├── answers_controller.rb │ ├── application_controller.rb │ ├── birthday_controller.rb │ ├── categories_controller.rb │ ├── close_reasons_controller.rb │ ├── comments_controller.rb │ ├── concerns │ │ └── .keep │ ├── custom_sessions_controller.rb │ ├── errors_controller.rb │ ├── flags_controller.rb │ ├── licenses_controller.rb │ ├── mod_warning_controller.rb │ ├── moderator_controller.rb │ ├── notifications_controller.rb │ ├── pinned_links_controller.rb │ ├── post_history_controller.rb │ ├── posts_controller.rb │ ├── questions_controller.rb │ ├── reports_controller.rb │ ├── search_controller.rb │ ├── site_settings_controller.rb │ ├── subscriptions_controller.rb │ ├── suggested_edit_controller.rb │ ├── suspicious_votes_controller.rb │ ├── tag_sets_controller.rb │ ├── tags_controller.rb │ ├── tour_controller.rb │ ├── two_factor_controller.rb │ ├── users_controller.rb │ └── votes_controller.rb ├── helpers │ ├── abilities_helper.rb │ ├── admin_helper.rb │ ├── advertisement_helper.rb │ ├── answers_helper.rb │ ├── application_helper.rb │ ├── articles_helper.rb │ ├── birthday_helper.rb │ ├── categories_helper.rb │ ├── close_reasons_helper.rb │ ├── comments_helper.rb │ ├── errors_helper.rb │ ├── flags_helper.rb │ ├── licenses_helper.rb │ ├── markdown_tools_helper.rb │ ├── mod_warning_helper.rb │ ├── moderator_helper.rb │ ├── notifications_helper.rb │ ├── pinned_links_helper.rb │ ├── post_types_helper.rb │ ├── posts_helper.rb │ ├── questions_helper.rb │ ├── reports_helper.rb │ ├── search_helper.rb │ ├── site_settings_helper.rb │ ├── subscriptions_helper.rb │ ├── suggested_edit_helper.rb │ ├── suspicious_votes_helper.rb │ ├── tabs_helper.rb │ ├── tag_sets_helper.rb │ ├── tags_helper.rb │ ├── tour_helper.rb │ ├── two_factor_helper.rb │ ├── uploads_helper.rb │ ├── users_helper.rb │ └── votes_helper.rb ├── mailers │ ├── .keep │ ├── admin_mailer.rb │ ├── application_mailer.rb │ ├── subscription_mailer.rb │ └── two_factor_mailer.rb ├── models │ ├── .keep │ ├── ability.rb │ ├── ability_queue.rb │ ├── answer.rb │ ├── application_record.rb │ ├── article.rb │ ├── audit_log.rb │ ├── blocked_item.rb │ ├── category.rb │ ├── close_reason.rb │ ├── comment.rb │ ├── community.rb │ ├── community_user.rb │ ├── concerns │ │ ├── .keep │ │ ├── community_related.rb │ │ ├── maybe_community_related.rb │ │ └── post_related.rb │ ├── error_log.rb │ ├── flag.rb │ ├── help_doc.rb │ ├── license.rb │ ├── mod_warning.rb │ ├── notification.rb │ ├── pinned_link.rb │ ├── policy_doc.rb │ ├── post.rb │ ├── post_flag_type.rb │ ├── post_history.rb │ ├── post_history_tag.rb │ ├── post_history_type.rb │ ├── post_type.rb │ ├── question.rb │ ├── request_context.rb │ ├── site_setting.rb │ ├── subscription.rb │ ├── suggested_edit.rb │ ├── suspicious_vote.rb │ ├── tag.rb │ ├── tag_set.rb │ ├── tag_with_path.rb │ ├── user.rb │ ├── user_ability.rb │ ├── vote.rb │ └── warning_template.rb └── views │ ├── abilities │ ├── index.html.erb │ └── show.html.erb │ ├── admin │ ├── _error_report.html.erb │ ├── _log_table.html.erb │ ├── admin_email.html.erb │ ├── audit_log.html.erb │ ├── error_reports.html.erb │ ├── index.html.erb │ └── privileges.html.erb │ ├── admin_mailer │ ├── to_moderators.html.erb │ └── to_moderators.text.erb │ ├── advertisement │ └── index.html.erb │ ├── application │ ├── dashboard.html.erb │ └── keyboard_tools.html.erb │ ├── birthday │ ├── index.html.erb │ └── ranking.html.erb │ ├── categories │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── new.html.erb │ ├── post_types.html.erb │ ├── rss_feed.rss.builder │ └── show.html.erb │ ├── close_reasons │ ├── edit.html.erb │ ├── index.html.erb │ └── new.html.erb │ ├── comments │ ├── _comment.html.erb │ └── post.html.erb │ ├── custom_sessions │ └── verify_2fa.html.erb │ ├── devise │ ├── confirmations │ │ └── new.html.erb │ ├── mailer │ │ ├── _friendly_footer.html.erb │ │ ├── confirmation_instructions.html.erb │ │ ├── email_changed.html.erb │ │ ├── password_change.html.erb │ │ ├── reset_password_instructions.html.erb │ │ └── unlock_instructions.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 │ ├── errors │ ├── conflict.html.erb │ ├── error.html.erb │ ├── forbidden.html.erb │ ├── internal_server_error.html.erb │ ├── locked.html.erb │ ├── not_found.html.erb │ ├── stat.html.erb │ └── unprocessable_entity.html.erb │ ├── flags │ ├── _handled.html.erb │ ├── handled.html.erb │ ├── history.html.erb │ └── queue.html.erb │ ├── layouts │ ├── _footer.html.erb │ ├── _head.html.erb │ ├── _header.html.erb │ ├── _matomo.html.erb │ ├── _sidebar.html.erb │ ├── application.html.erb │ ├── devise_mailer.html.erb │ ├── mailer.html.erb │ ├── mailer.text.erb │ └── without_sidebar.html.erb │ ├── licenses │ ├── _form.html.erb │ ├── _license.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ └── new.html.erb │ ├── mod_warning │ ├── current.html.erb │ ├── log.html.erb │ └── new.html.erb │ ├── moderator │ ├── index.html.erb │ ├── recent_comments.html.erb │ └── recently_deleted_posts.html.erb │ ├── notifications │ └── index.erb │ ├── pinned_links │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ └── new.html.erb │ ├── post_history │ ├── _diff.html.erb │ └── post.html.erb │ ├── posts │ ├── _article_list.html.erb │ ├── _expanded.html.erb │ ├── _form.html.erb │ ├── _help_center_posts.html.erb │ ├── _image_upload.html.erb │ ├── _list.html.erb │ ├── _markdown_script.html.erb │ ├── _mdhint.html.erb │ ├── _post_tools.html.erb │ ├── _toc_entry.html.erb │ ├── _type_agnostic.html.erb │ ├── document.html.erb │ ├── edit.html.erb │ ├── help_center.html.erb │ ├── new.html.erb │ └── show.html.erb │ ├── questions │ ├── _list.html.erb │ ├── feed.rss.builder │ └── lottery.html.erb │ ├── reports │ ├── _tabs.html.erb │ ├── posts.html.erb │ ├── subscriptions.html.erb │ └── users.html.erb │ ├── search │ └── search.html.erb │ ├── shared │ ├── _body_field.html.erb │ └── _markdown_tools.html.erb │ ├── site_settings │ ├── edit.html.erb │ └── index.html.erb │ ├── subscription_mailer │ ├── subscription.html.erb │ └── subscription.text.erb │ ├── subscriptions │ ├── error.html.erb │ ├── index.html.erb │ └── new.html.erb │ ├── suggested_edit │ └── show.html.erb │ ├── suspicious_votes │ ├── index.html.erb │ └── user.html.erb │ ├── tag_sets │ └── index.html.erb │ ├── tags │ ├── _list.html.erb │ ├── _tag.html.erb │ ├── category.html.erb │ ├── children.html.erb │ ├── edit.html.erb │ ├── select_merge.html.erb │ ├── show.html.erb │ └── show.rss.builder │ ├── tour │ ├── end.html.erb │ ├── index.html.erb │ ├── more.html.erb │ ├── question1.html.erb │ ├── question2.html.erb │ └── question3.html.erb │ ├── two_factor │ ├── disable_code.html.erb │ ├── disable_link.html.erb │ ├── enable_2fa.html.erb │ ├── enable_code.html.erb │ └── tf_status.html.erb │ ├── two_factor_mailer │ ├── disable_email.html.erb │ ├── disable_email.text.erb │ ├── login_email.html.erb │ └── login_email.text.erb │ └── users │ ├── _post_usercard.html.erb │ ├── _tabs.html.erb │ ├── _user.html.erb │ ├── activity.html.erb │ ├── annotations.html.erb │ ├── edit_profile.erb │ ├── full_log.html.erb │ ├── index.html.erb │ ├── mod.html.erb │ ├── mod_privileges.html.erb │ ├── posts.html.erb │ ├── qr_login_code.html.erb │ └── show.html.erb ├── bin ├── bundle ├── rails ├── rake ├── setup └── spring ├── config.ru ├── config ├── application.rb ├── boot.rb ├── credentials.yml.enc ├── database.docker.yml ├── database.sample.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── activerecord_relation.rb │ ├── amazon_ses.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── devise.rb │ ├── devise_example.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── namespaced_cache.rb │ ├── session_store.rb │ ├── wrap_parameters.rb │ ├── zz_cache_setup.rb │ └── zz_codidact_sites.rb ├── locales │ ├── devise.en.yml │ ├── en.yml │ ├── es.yml │ ├── strings │ │ ├── en.admin.yml │ │ ├── en.ads.yml │ │ ├── en.g.yml │ │ ├── en.posts.yml │ │ ├── en.rate_limit.yml │ │ ├── es.admin.yml │ │ ├── es.ads.yml │ │ └── es.g.yml │ ├── time.en_abbrev.yml │ └── time.es_abbrev.yml ├── routes.rb ├── schedule.rb ├── secrets.yml └── storage.sample.yml ├── db ├── migrate │ ├── 20160424111225_devise_create_users.rb │ ├── 20160424111446_add_user_levels_to_users.rb │ ├── 20160424113217_create_site_settings.rb │ ├── 20160424143518_create_questions.rb │ ├── 20160424143813_add_user_to_questions.rb │ ├── 20160424162234_add_rep_and_name_to_users.rb │ ├── 20160424172308_create_answers.rb │ ├── 20160424172323_add_question_to_answer.rb │ ├── 20160424172807_add_user_to_answers.rb │ ├── 20160424183802_create_votes.rb │ ├── 20160424183824_add_user_and_post_to_votes.rb │ ├── 20160424191151_remove_post_from_votes.rb │ ├── 20160424191405_add_polymorphic_post_to_votes.rb │ ├── 20160424193831_rename_votes_type_to_votes_vote_type.rb │ ├── 20160428151443_add_user_to_privileges.rb │ ├── 20160428151900_add_name_to_privileges.rb │ ├── 20160428152011_add_threshold_to_privileges.rb │ ├── 20160428202611_add_is_deleted_to_questions.rb │ ├── 20160429150239_add_is_deleted_to_answers.rb │ ├── 20160429160133_add_deleted_at_to_questions.rb │ ├── 20160429160144_add_deleted_at_to_answers.rb │ ├── 20160430085505_create_notifications.rb │ ├── 20160430085520_add_user_to_notifications.rb │ ├── 20160430092324_add_default_false_value_to_notifications.rb │ ├── 20160501095155_create_comments.rb │ ├── 20160501095354_add_post_to_comments.rb │ ├── 20160501101156_add_content_to_comments.rb │ ├── 20160501103643_add_is_deleted_to_comments.rb │ ├── 20160501105740_add_user_to_comments.rb │ ├── 20160501150244_create_flags.rb │ ├── 20160501150316_create_flag_statuses.rb │ ├── 20160501150344_add_user_to_flags.rb │ ├── 20160501150355_add_polymorphic_post_to_flags.rb │ ├── 20160501150425_add_flag_to_flag_statuses.rb │ ├── 20160501203952_add_default_to_is_deleted.rb │ ├── 20160507112321_create_post_history_types.rb │ ├── 20160507112635_create_post_histories.rb │ ├── 20160507112646_add_post_to_post_history.rb │ ├── 20160507135329_remove_post_fields_from_post_history.rb │ ├── 20160615175537_add_defaults_to_deleted.rb │ ├── 20160619161305_add_receiving_user_to_votes.rb │ ├── 20160619162714_create_suspicious_votes.rb │ ├── 20160621093334_rename_user_attributes.rb │ ├── 20160621102440_create_join_table_privilege_user.rb │ ├── 20160621145835_add_close_fields_to_questions.rb │ ├── 20160621174102_rename_closed_by_to_closed_by_id.rb │ ├── 20191109211244_change_site_settings_value_type.rb │ ├── 20191110173829_move_to_single_post_model.rb │ ├── 20191110193734_remove_polymorphic_assoc_fields.rb │ ├── 20191110205100_rename_comments_is_deleted.rb │ ├── 20191110212601_add_post_defaults.rb │ ├── 20191120165535_remove_action_name_from_post_history_types.rb │ ├── 20191120170439_remove_user_id_from_privileges.rb │ ├── 20191122124913_change_recv_user_field_name_on_votes.rb │ ├── 20191124214828_add_value_type_to_site_settings.rb │ ├── 20191125135227_add_description_to_site_settings.rb │ ├── 20191125145708_add_name_indexes.rb │ ├── 20191127121809_add_body_markdown_to_posts.rb │ ├── 20191202195956_add_profile_attributes_to_user.rb │ ├── 20191202215751_add_profile_markdown_to_users.rb │ ├── 20191204172132_create_tags.rb │ ├── 20191204172148_create_post_tags_link_table.rb │ ├── 20191204172543_rename_posts_tags.rb │ ├── 20191205115827_add_answer_count_to_posts.rb │ ├── 20191205122016_add_default_to_answer_count.rb │ ├── 20191205122434_add_last_activity_to_posts.rb │ ├── 20191205123038_rework_flag_system_tables.rb │ ├── 20191205123408_add_handled_at_to_flags.rb │ ├── 20191205135001_create_active_storage_tables.active_storage.rb │ ├── 20191205155835_add_state_fields_to_post_history.rb │ ├── 20191205212204_add_attribution_fields_to_post.rb │ ├── 20191205225500_add_se_acct_id_to_users.rb │ ├── 20191206213515_add_transferred_content_to_users.rb │ ├── 20191207001359_add_search_fulltext_index_to_posts.rb │ ├── 20191207011614_add_is_meta_to_posts.rb │ ├── 20191208231830_add_doc_slug_to_posts.rb │ ├── 20191215183139_add_last_activity_by_to_posts.rb │ ├── 20191215211744_change_comments_content_field_type.rb │ ├── 20191216161051_add_users_username_index.rb │ ├── 20191217000359_add_comment_to_post_history.rb │ ├── 20191225135200_add_category_to_site_settings.rb │ ├── 20191225141700_add_setting_categories.rb │ ├── 20200109205444_change_settings_to_text_type.rb │ ├── 20200115221655_create_subscriptions.rb │ ├── 20200116005738_add_name_to_subscriptions.rb │ ├── 20200116132702_add_default_to_subscriptions_enabled.rb │ ├── 20200116132808_allow_null_subscriptions_last_sent.rb │ ├── 20200122151548_add_category_to_posts.rb │ ├── 20200128123353_move_is_meta_to_category.rb │ ├── 20200202052500_create_communities_table.rb │ ├── 20200317173232_close_reasons.rb │ ├── 20200318161617_add_comunity_scope_to_close_reasons.rb │ ├── 20200318164203_add_index_to_flags_status.rb │ ├── 20200321135935_create_tag_sets.rb │ ├── 20200321135945_add_tag_set_reference_to_tags.rb │ ├── 20200323131708_add_indexes_to_posts.rb │ ├── 20200411195247_create_categories.rb │ ├── 20200411195809_move_posts_to_category_reference.rb │ ├── 20200411210022_create_categories_post_types.rb │ ├── 20200412121936_correct_close_reasons_reference_attribute_name.rb │ ├── 20200412122236_add_display_post_types_to_categories.rb │ ├── 20200413144332_add_is_homepage_to_categories.rb │ ├── 20200413174714_add_tag_set_reference_to_categories.rb │ ├── 20200420151217_add_trust_level_to_users.rb │ ├── 20200420151720_add_min_trust_level_to_categories.rb │ ├── 20200422152359_add_button_text_to_categories.rb │ ├── 20200428172814_create_licenses.rb │ ├── 20200428173033_add_license_reference_to_posts.rb │ ├── 20200428181938_add_customization_fields_to_category.rb │ ├── 20200430123008_add_posting_tips_overrides_to_category.rb │ ├── 20200430220415_create_error_logs.rb │ ├── 20200430220944_add_uuid_to_error_logs.rb │ ├── 20200501215447_add_min_view_trust_level_to_categories.rb │ ├── 20200502001225_add_license_reference_to_categories.rb │ ├── 20200502152723_add_enabled_to_licenses.rb │ ├── 20200503110754_add_qr_login_attributes_to_user.rb │ ├── 20200504213143_add_two_factor_token_to_users.rb │ ├── 20200507235849_add_user_agent_to_error_logs.rb │ ├── 20200508112958_add_sequence_to_categories.rb │ ├── 20200508115752_add_category_tag_join_tables.rb │ ├── 20200512115318_create_suggested_edits.rb │ ├── 20200515212247_add_post_indexes.rb │ ├── 20200516162625_update_answer_count_column.rb │ ├── 20200517105207_add_confirmable_to_devise.rb │ ├── 20200528145307_add_two_factor_method_to_users.rb │ ├── 20200601113238_add_index_to_last_activity.rb │ ├── 20200610150214_add_help_attributes_to_posts.rb │ ├── 20200610152505_allow_post_community_id_null.rb │ ├── 20200610152647_allow_post_history_community_id_null.rb │ ├── 20200612154828_add_unique_index_to_posts_tags.rb │ ├── 20200616224440_change_to_wilson_scores.rb │ ├── 20200617140007_change_post_score_column_type.rb │ ├── 20200618094826_add_suspensions_and_warnings.rb │ ├── 20200618124645_add_warning_templates.rb │ ├── 20200625115618_add_mod_tags_join_table.rb │ ├── 20200629131408_update_tag_model.rb │ ├── 20200630001048_remove_excerpt_markdown.rb │ ├── 20200630105117_allow_tag_parents.rb │ ├── 20200701132522_add_index_to_post_score.rb │ ├── 20200701132654_add_indexes_to_vote_counts.rb │ ├── 20200709204628_create_audit_logs.rb │ ├── 20200709204728_add_audit_indexes.rb │ ├── 20200711121645_add_community_to_audit_logs.rb │ ├── 20200716081538_create_blocked_items.rb │ ├── 20200716191141_add_comments_disabled_to_posts.rb │ ├── 20200718163608_rename_type_column_of_blocked_items.rb │ ├── 20200721185048_add_title_and_tags_to_post_history.rb │ ├── 20200721185230_create_post_history_tags.rb │ ├── 20200727183756_create_pinned_links.rb │ ├── 20200728093322_add_eligible_for_hot_post_to_category.rb │ ├── 20200806103121_add_staff_to_users.rb │ ├── 20200810153141_create_trust_levels.rb │ ├── 20200810153831_create_user_privileges.rb │ ├── 20200813125349_rename_ability_tables.rb │ ├── 20200813132829_enforce_concurrence_of_is_moderator_and_mod_ability.rb │ ├── 20200813141412_have_two_descriptions_on_abilities.rb │ ├── 20200814203051_create_post_flag_types.rb │ ├── 20200815103111_add_post_flag_type_id_to_flags.rb │ ├── 20200815191909_add_locked_to_posts.rb │ ├── 20200815193704_add_locked_until_to_posts.rb │ ├── 20200829235149_add_edit_fields_to_post.rb │ ├── 20200910103140_add_before_columns_to_suggested_edit.rb │ ├── 20201001085031_add_read_to_mod_warning.rb │ ├── 20201118222120_create_ability_queues.rb │ ├── 20201123132854_add_lockable_omniauthable.rb │ ├── 20201204170746_add_columns_to_post_type.rb │ ├── 20201212235514_move_trust_level_to_community_user.rb │ └── 20201216225353_add_is_freely_editable_to_post_types.rb ├── schema.rb ├── scripts │ ├── create_tags_path_view.rb │ ├── create_tags_path_view.sql │ ├── reset_collations.rb │ └── tag_children.sql ├── seeds.rb └── seeds │ ├── abilities.yml │ ├── abilities │ ├── edit_posts.html │ ├── edit_tags.html │ ├── everyone.html │ ├── flag_close.html │ ├── flag_curate.html │ ├── mod.html │ └── unrestricted.html │ ├── categories.yml │ ├── close_reasons.yml │ ├── licenses.yml │ ├── post_flag_types.yml │ ├── post_history_types.yml │ ├── post_types.yml │ ├── posts.yml │ ├── posts │ ├── abilities.html │ ├── alt-text.html │ ├── articles.html │ ├── category-permissions.html │ ├── coc.html │ ├── deleted.html │ ├── formatting.html │ ├── global_faq.html │ ├── how-to-ask.html │ ├── licenses.html │ ├── local_faq.html │ ├── moderator.html │ ├── referencing.html │ ├── scoring.html │ ├── search.html │ ├── spam.html │ ├── tos.html │ ├── voting.html │ └── warnings.html │ ├── site_settings.yml │ ├── site_settings │ └── asking_guidance.html │ ├── tag_sets.yml │ ├── users.yml │ ├── warning_templates.yml │ └── warning_templates │ ├── off-topic.md │ ├── rudeness.md │ └── spam.md ├── docker-compose.yml ├── docker ├── Dockerfile ├── Dockerfile.db ├── README.md ├── compose-env ├── create_admin_and_community.rb ├── dummy.env ├── entrypoint.sh ├── img │ ├── categories.png │ ├── create-post.png │ ├── interface.png │ ├── logged-in.png │ ├── post.png │ ├── tagset-selected.png │ └── tagset.png ├── local-setup.sh └── mysql-init.sql ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── assets │ ├── ability-help │ │ ├── close-dialog.png │ │ ├── edit-link.png │ │ ├── flag-dialog.png │ │ ├── flag-inline-handling.png │ │ └── voting.png │ ├── birthday.svg │ ├── codidact-org.png │ ├── codidactyl.png │ ├── community │ │ ├── judaism.css │ │ └── judaism.js │ ├── down-clear.png │ ├── down-fill.png │ ├── favicon.png │ ├── logo-writing.png │ ├── logo.png │ ├── privacy-policy.pdf │ ├── scoring_3d.png │ ├── scoring_distribution.png │ ├── scoring_formula.png │ ├── scoring_table.png │ ├── tour-clippy.png │ ├── tour-evil.png │ ├── up-clear.png │ └── up-fill.png ├── favicon.ico └── robots.txt ├── scripts ├── change_to_wilson_scores.rb ├── clear_cache.rb ├── create_initial_tags.rb ├── import │ ├── api_import.rb │ ├── database_import.rb │ ├── dump_import.rb │ └── stack_import.rb ├── recalc_abilities.rb ├── recalc_abilities_upon_first_migration.rb ├── remove_exact_duplicates.sql ├── rep_recalc_community.sql ├── send_subscription_emails.rb └── wipe_everything.rb ├── test ├── .rubocop.yml ├── controllers │ ├── .keep │ ├── abilities_controller_test.rb │ ├── admin_controller_test.rb │ ├── advertisement_controller_test.rb │ ├── answers_controller_test.rb │ ├── articles_controller_test.rb │ ├── birthday_controller_test.rb │ ├── categories_controller_test.rb │ ├── close_reasons_controller_test.rb │ ├── comments_controller_test.rb │ ├── flags_controller_test.rb │ ├── licenses_controller_test.rb │ ├── mod_warning_controller_test.rb │ ├── moderator_controller_test.rb │ ├── notifications_controller_test.rb │ ├── pinned_links_controller_test.rb │ ├── post_history_controller_test.rb │ ├── posts_controller_test.rb │ ├── questions_controller_test.rb │ ├── reports_controller_test.rb │ ├── search_controller_test.rb │ ├── site_settings_controller_test.rb │ ├── subscriptions_controller_test.rb │ ├── suggested_edit_controller_test.rb │ ├── suspicious_votes_controller_test.rb │ ├── tag_sets_controller_test.rb │ ├── tags_controller_test.rb │ ├── tour_controller_test.rb │ ├── two_factor_controller_test.rb │ ├── users_controller_test.rb │ └── votes_controller_test.rb ├── fixtures │ ├── .keep │ ├── abilities.yml │ ├── ability_queues.yml │ ├── audit_logs.yml │ ├── blocked_items.yml │ ├── categories.yml │ ├── close_reasons.yml │ ├── comments.yml │ ├── communities.yml │ ├── community_users.yml │ ├── error_logs.yml │ ├── flags.yml │ ├── licenses.yml │ ├── mod_warnings.yml │ ├── notifications.yml │ ├── pinned_links.yml │ ├── post_flag_types.yml │ ├── post_histories.yml │ ├── post_history_tags.yml │ ├── post_history_types.yml │ ├── post_types.yml │ ├── posts.yml │ ├── site_settings.yml │ ├── subscriptions.yml │ ├── suggested_edits.yml │ ├── suspicious_votes.yml │ ├── tag_sets.yml │ ├── tags.yml │ ├── user_abilities.yml │ ├── users.yml │ ├── votes.yml │ └── warning_templates.yml ├── helpers │ ├── .keep │ └── search_helper_test.rb ├── integration │ └── .keep ├── mailers │ ├── .keep │ ├── admin_mailer_test.rb │ ├── previews │ │ ├── admin_mailer_preview.rb │ │ ├── devise_mailer_preview.rb │ │ ├── subscription_mailer_preview.rb │ │ └── two_factor_mailer_preview.rb │ ├── subscription_mailer_test.rb │ └── two_factor_mailer_test.rb ├── models │ ├── .keep │ ├── ability_queue_test.rb │ ├── ability_test.rb │ ├── audit_log_test.rb │ ├── blocked_item_test.rb │ ├── category_test.rb │ ├── comment_test.rb │ ├── error_log_test.rb │ ├── flag_status_test.rb │ ├── flag_test.rb │ ├── license_test.rb │ ├── mod_warning_test.rb │ ├── notification_test.rb │ ├── pinned_link_test.rb │ ├── post_flag_type_test.rb │ ├── post_history_tag_test.rb │ ├── post_history_test.rb │ ├── post_history_type_test.rb │ ├── post_test.rb │ ├── request_context_test.rb │ ├── site_setting_test.rb │ ├── subscription_test.rb │ ├── suggested_edit_test.rb │ ├── suspicious_vote_test.rb │ ├── tag_set_test.rb │ ├── tag_test.rb │ ├── user_ability_test.rb │ ├── user_test.rb │ ├── vote_test.rb │ └── warning_template_test.rb ├── support │ ├── application_test_helper.rb │ └── community_related_helper.rb └── test_helper.rb └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | before_script: 2 | - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs 3 | - ruby -v 4 | - which ruby 5 | - gem install bundler --no-ri --no-rdoc 6 | - cp config/letsencrypt_plugin.example.yml config/letsencrypt_plugin.yml 7 | - bundle install --jobs $(nproc) "${FLAGS[@]}" 8 | - bundle exec rake db:create db:schema:load 9 | - bundle exec rake test:prepare 10 | - bundle exec rake db:migrate 11 | - bundle exec rake db:seed 12 | 13 | test_unit: 14 | script: 15 | - bundle exec rake test 16 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('config/application', __dir__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/christianity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/christianity.png -------------------------------------------------------------------------------- /app/assets/images/codegolf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/codegolf.png -------------------------------------------------------------------------------- /app/assets/images/codidact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/codidact.png -------------------------------------------------------------------------------- /app/assets/images/cooking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/cooking.png -------------------------------------------------------------------------------- /app/assets/images/electrical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/electrical.png -------------------------------------------------------------------------------- /app/assets/images/fbm.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/fbm.ico -------------------------------------------------------------------------------- /app/assets/images/judaism.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/judaism.png -------------------------------------------------------------------------------- /app/assets/images/languages-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/languages-mobile.png -------------------------------------------------------------------------------- /app/assets/images/languages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/languages.png -------------------------------------------------------------------------------- /app/assets/images/logo-photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/logo-photo.png -------------------------------------------------------------------------------- /app/assets/images/logo-writing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/logo-writing.png -------------------------------------------------------------------------------- /app/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/logo.png -------------------------------------------------------------------------------- /app/assets/images/math.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/math.png -------------------------------------------------------------------------------- /app/assets/images/meta-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/meta-logo.png -------------------------------------------------------------------------------- /app/assets/images/meta-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/meta-mobile.png -------------------------------------------------------------------------------- /app/assets/images/meta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/meta.png -------------------------------------------------------------------------------- /app/assets/images/outdoors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/outdoors.png -------------------------------------------------------------------------------- /app/assets/images/software-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/software-full.png -------------------------------------------------------------------------------- /app/assets/images/software-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/software-mobile.png -------------------------------------------------------------------------------- /app/assets/images/specsci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/specsci.png -------------------------------------------------------------------------------- /app/assets/images/square.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/images/square.ico -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Black-FRLHebrew.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Black-FRLHebrew.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Black.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-BlackItalic.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-BoldItalic.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Italic.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Light.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-LightItalic.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-MediumItalic.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-Thin.ttf -------------------------------------------------------------------------------- /app/assets/imgfonts/Roboto-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/imgfonts/Roboto-ThinItalic.ttf -------------------------------------------------------------------------------- /app/assets/javascripts/abilities.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/advertisement.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/assets/javascripts/advertisement.js -------------------------------------------------------------------------------- /app/assets/javascripts/birthday.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/licenses.js: -------------------------------------------------------------------------------- 1 | $(() => { 2 | $('.js-license-autofill').on('click', ev => { 3 | const $tgt = $(ev.target); 4 | const $input = $tgt.parents('.form-group').find('select'); 5 | const licenseId = $tgt.attr('data-license-id'); 6 | $input.val(licenseId).trigger('change'); 7 | }); 8 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/mod_warning.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | $(".js--warning-template-selection").on("input", (e) => { 3 | const $this = $(e.target); 4 | $(".js--warning-template-target textarea").val(atob($this.val())); 5 | }); 6 | }) -------------------------------------------------------------------------------- /app/assets/javascripts/modals.js: -------------------------------------------------------------------------------- 1 | $(() => { 2 | $(document).on('keydown', ev => { 3 | if (ev.keyCode === 27) { // Esc 4 | $('.modal').removeClass('is-active'); 5 | } 6 | }); 7 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/moderator.js: -------------------------------------------------------------------------------- 1 | $(() => { 2 | $('.js-convert-to-comment, .js-toggle-comments, .js-feature-post, .js-lock').on('ajax:success', ev => { 3 | location.reload(); 4 | }); 5 | }); -------------------------------------------------------------------------------- /app/assets/javascripts/pinned_links.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/abilities.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the abilities controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/advertisement.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Advertisement controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/articles.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Articles controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/categories.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Categories controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | 5 | @import './variables'; 6 | 7 | .category-meta { 8 | display: flex; 9 | border-bottom: 1px solid $muted-graphic; 10 | flex-direction: column; 11 | align-items: center; 12 | justify-content: flex-start; 13 | 14 | @media screen and (min-width: $screen-md) { 15 | flex-direction: row; 16 | align-items: center; 17 | justify-content: space-between; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/assets/stylesheets/close_reasons.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the CloseReasons controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/comments.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .comment { 4 | display: flex; 5 | flex-direction: column; 6 | border-bottom: 1px solid $muted-graphic; 7 | padding: 0.5em; 8 | align-items: stretch; 9 | max-width: 100%; 10 | overflow: auto; 11 | 12 | .comment--content { 13 | margin-bottom: 0; 14 | } 15 | 16 | .comment--meta { 17 | margin-left: auto; 18 | } 19 | } 20 | 21 | .comment-form { 22 | margin-top: 0.5em; 23 | } 24 | .post--comments { 25 | font-size: 0.9em; 26 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/errors.scss: -------------------------------------------------------------------------------- 1 | .error-code { 2 | font-size: 8rem; 3 | padding: 0; 4 | margin: -0.3em 0; 5 | } 6 | 7 | .error-name { 8 | font-variant: small-caps; 9 | letter-spacing: 10px; 10 | font-weight: bold; 11 | padding: 0; 12 | margin: 0; 13 | } 14 | 15 | .error-trace { 16 | background: #EEE; 17 | height: unset; 18 | max-height: unset; 19 | white-space: pre-wrap; 20 | word-wrap: break-word; 21 | } 22 | 23 | .error-report-summary { 24 | display: flex; 25 | align-items: center; 26 | 27 | .details { 28 | flex: 1; 29 | } 30 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/keyboard_tools.scss: -------------------------------------------------------------------------------- 1 | .__keyboard_help { 2 | padding: 1rem; 3 | font-family: monospace; 4 | white-space: pre-wrap; 5 | width: 350px; 6 | background-color: rgba(0,0,0,0.8); 7 | color: white; 8 | border-radius: 0.25rem; 9 | position: fixed; 10 | left: 1rem; 11 | bottom: 1rem; 12 | z-index: 2305843009213693951; /* This is the largest Mersenne-prime shown in full on Wikipedia and should be 13 | large enough for most practical use cases to ensure that the keyboard help 14 | is always above everything else. */ 15 | } 16 | .__keyboard_selected { 17 | outline: 0.25rem solid red; 18 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/licenses.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Licenses controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/markdown_tools.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | .markdown-tools { 4 | display: flex; 5 | flex-direction: row; 6 | flex-wrap: wrap; 7 | align-items: flex-start; 8 | 9 | .button-list { 10 | margin: 0 0.3em 0.3em 0; 11 | } 12 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/mod_warning.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the ModWarning controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/notifications.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .notification { 4 | border-top: 1px solid $muted-graphic; 5 | padding: 0.5em; 6 | 7 | @media screen and (min-width: $screen-md) { 8 | flex-direction: row; 9 | } 10 | 11 | & > * { 12 | margin: 0 0.2em; 13 | } 14 | 15 | &:last-of-type { 16 | border-bottom: 1px solid $muted-graphic; 17 | } 18 | 19 | .notification--timestamp { 20 | line-break: strict; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/pinned_links.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the PinnedLinks controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/post_history.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .history-event { 4 | border-top: 1px solid $muted-graphic; 5 | padding: 1em; 6 | 7 | & > :not(summary) { 8 | margin-top: 0.5em; 9 | } 10 | 11 | &:last-of-type { 12 | border-bottom: 1px solid $muted-graphic; 13 | } 14 | 15 | .before { 16 | flex: 1; 17 | padding: 0.5em; 18 | background: lighten($danger, 55%); 19 | } 20 | 21 | .after { 22 | flex: 1; 23 | padding: 0.5em; 24 | background: lighten($success, 45%); 25 | } 26 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/reports.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Reports controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/site_settings.scss: -------------------------------------------------------------------------------- 1 | .site-setting--value { 2 | min-height: 1em; 3 | min-width: 2em; 4 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/subscriptions.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Subscriptions controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/suggested_edit.scss: -------------------------------------------------------------------------------- 1 | .js-suggested-edit-reject-dialog.is-hidden { 2 | display: none; 3 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/tabs.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .tabs { 4 | margin-bottom: 1em; 5 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/tag_sets.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the TagSets controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | 5 | .item-list.is-flex-centered .item-list--text-value { 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | justify-content: center; 10 | 11 | &.is-primary { 12 | align-items: flex-start; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/tags.scss: -------------------------------------------------------------------------------- 1 | .tag-cell { 2 | margin: 0.5em 0; 3 | 4 | &:hover { 5 | background: #f0f2ff; 6 | transition: all 0.3s ease; 7 | border-radius: 0.2em; 8 | } 9 | 10 | p { 11 | margin: 0; 12 | } 13 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/tour.scss: -------------------------------------------------------------------------------- 1 | .codidactyl { 2 | width: 80px; 3 | padding: 2rem; 4 | margin-top: 1rem; 5 | } 6 | .codidactyl + .is-flexible { width: 0; } 7 | 8 | .codidactyl-sticky { 9 | position: sticky; 10 | top: 0.5rem; 11 | padding: 1rem; 12 | } 13 | 14 | .codidactyl-small { 15 | max-height: 1em; 16 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/two_factor.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the two_factor controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/controllers/birthday_controller.rb: -------------------------------------------------------------------------------- 1 | class BirthdayController < ApplicationController 2 | def index 3 | render layout: 'without_sidebar' 4 | end 5 | 6 | def ranking 7 | @ranking = Rails.cache.fetch('birthday-ranking', expires_in: 1.hour) do 8 | User.unscoped.joins('INNER JOIN posts ON posts.user_id = users.id').where('posts.score > 0.6') \ 9 | .where('posts.created_at >= \'2020-10-16\' AND posts.created_at <= \'2020-10-23\'') \ 10 | .where(staff: false).group('posts.user_id').select('users.*', 'count(posts.id) as post_count') \ 11 | .order('post_count DESC, users.created_at DESC').all 12 | end 13 | render layout: 'without_sidebar' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/moderator_controller.rb: -------------------------------------------------------------------------------- 1 | # Web controller. Provides authenticated actions for use by moderators. A lot of the stuff in here, and hence a lot of 2 | # the tools, are rather repetitive. 3 | class ModeratorController < ApplicationController 4 | before_action :verify_moderator 5 | 6 | def index; end 7 | 8 | def recently_deleted_posts 9 | @posts = Post.unscoped.where(community: @community, deleted: true).order('deleted_at DESC') 10 | .paginate(page: params[:page], per_page: 50) 11 | end 12 | 13 | def recent_comments 14 | @comments = Comment.all.includes(:user, :post).order(created_at: :desc).paginate(page: params[:page], per_page: 50) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/controllers/post_history_controller.rb: -------------------------------------------------------------------------------- 1 | class PostHistoryController < ApplicationController 2 | def post 3 | @post = Post.find(params[:id]) 4 | @history = PostHistory.where(post_id: params[:id]).includes(:post_history_type, :user, post_history_tags: [:tag]) 5 | .order(created_at: :desc).paginate(per_page: 20, page: params[:page]) 6 | render layout: 'without_sidebar' 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/tour_controller.rb: -------------------------------------------------------------------------------- 1 | class TourController < ApplicationController 2 | layout 'without_sidebar' 3 | 4 | def index; end 5 | 6 | def question1; end 7 | 8 | def question2; end 9 | 10 | def question3; end 11 | 12 | def more 13 | @communities = Community.all 14 | end 15 | 16 | def end; end 17 | end 18 | -------------------------------------------------------------------------------- /app/helpers/admin_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under AdminController. 2 | module AdminHelper 3 | end 4 | -------------------------------------------------------------------------------- /app/helpers/answers_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under AnswersController. 2 | module AnswersHelper 3 | def my_vote(answer) 4 | user_signed_in? ? answer.votes.where(user: current_user).first : nil 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/articles_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticlesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/birthday_helper.rb: -------------------------------------------------------------------------------- 1 | module BirthdayHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/close_reasons_helper.rb: -------------------------------------------------------------------------------- 1 | module CloseReasonsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/comments_helper.rb: -------------------------------------------------------------------------------- 1 | module CommentsHelper 2 | end 3 | 4 | class CommentScrubber < Rails::Html::PermitScrubber 5 | def initialize 6 | super 7 | self.tags = %w[a b i em strong strike del code] 8 | self.attributes = %w[href title] 9 | end 10 | 11 | def skip_node?(node) 12 | node.text? 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/helpers/errors_helper.rb: -------------------------------------------------------------------------------- 1 | module ErrorsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/flags_helper.rb: -------------------------------------------------------------------------------- 1 | module FlagsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/licenses_helper.rb: -------------------------------------------------------------------------------- 1 | module LicensesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/markdown_tools_helper.rb: -------------------------------------------------------------------------------- 1 | module MarkdownToolsHelper 2 | def md_button(name = nil, action: nil, label: nil, **attribs, &block) 3 | attribs.merge! href: 'javascript:void(0)', 4 | class: "#{attribs[:class] || ''} button is-muted is-outlined js-markdown-tool", 5 | data_action: action, 6 | aria_label: label, 7 | title: label 8 | attribs.transform_keys! { |k| k.to_s.tr('_', '-') }.symbolize_keys! 9 | if name.nil? && block_given? 10 | tag.a(**attribs, &block) 11 | else 12 | tag.a name, **attribs 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/helpers/mod_warning_helper.rb: -------------------------------------------------------------------------------- 1 | module ModWarningHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/moderator_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under ModeratorController. 2 | module ModeratorHelper 3 | end 4 | -------------------------------------------------------------------------------- /app/helpers/notifications_helper.rb: -------------------------------------------------------------------------------- 1 | module NotificationsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/pinned_links_helper.rb: -------------------------------------------------------------------------------- 1 | module PinnedLinksHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/post_types_helper.rb: -------------------------------------------------------------------------------- 1 | module PostTypesHelper 2 | def post_type_badge(type) 3 | icon_class = { 4 | 'Question' => 'fas fa-question', 5 | 'Article' => 'fas fa-newspaper' 6 | }[type] 7 | tag.span class: 'badge is-tag is-filled is-muted' do 8 | tag.i(class: icon_class) + ' ' + tag.span(type) # rubocop:disable Style/StringConcatenation 9 | end 10 | end 11 | 12 | def post_type_criteria 13 | PostType.new.attributes.keys.select { |k| k.start_with?('has_') || k.start_with?('is_') }.map(&:to_sym) 14 | end 15 | 16 | def post_type_ids(**opts) 17 | key = post_type_criteria.map { |a| opts[a] ? '1' : '0' }.join 18 | Rails.cache.fetch "post_type_ids/#{key}" do 19 | PostType.where(**opts).select(:id).map(&:id) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/helpers/posts_helper.rb: -------------------------------------------------------------------------------- 1 | module PostsHelper 2 | def post_markdown(scope, field_name) 3 | params['__html'].presence || render_markdown(params[scope][field_name]) 4 | end 5 | 6 | class PostScrubber < Rails::Html::PermitScrubber 7 | def initialize 8 | super 9 | self.tags = %w[a p span b i em strong hr h1 h2 h3 h4 h5 h6 blockquote img strike del code pre br ul ol li sup sub 10 | section details summary ins table thead tbody tr th td] 11 | self.attributes = %w[id class href title src height width alt rowspan colspan lang] 12 | end 13 | 14 | def skip_node?(node) 15 | node.text? 16 | end 17 | end 18 | 19 | def scrubber 20 | PostsHelper::PostScrubber.new 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/helpers/questions_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under QuestionsController. 2 | module QuestionsHelper 3 | def my_vote(question) 4 | user_signed_in? ? question.votes.where(user: current_user).first : nil 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/reports_helper.rb: -------------------------------------------------------------------------------- 1 | module ReportsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/site_settings_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under SiteSettingsController. 2 | module SiteSettingsHelper 3 | end 4 | -------------------------------------------------------------------------------- /app/helpers/subscriptions_helper.rb: -------------------------------------------------------------------------------- 1 | module SubscriptionsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/suggested_edit_helper.rb: -------------------------------------------------------------------------------- 1 | module SuggestedEditHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/suspicious_votes_helper.rb: -------------------------------------------------------------------------------- 1 | module SuspiciousVotesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/tag_sets_helper.rb: -------------------------------------------------------------------------------- 1 | module TagSetsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/tour_helper.rb: -------------------------------------------------------------------------------- 1 | module TourHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/two_factor_helper.rb: -------------------------------------------------------------------------------- 1 | module TwoFactorHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/uploads_helper.rb: -------------------------------------------------------------------------------- 1 | module UploadsHelper 2 | def upload_remote_url(blob) 3 | bucket = Rails.cache.fetch 'active_storage/s3/bucket' do 4 | ActiveStorage::Blob.service.bucket.name 5 | end 6 | "https://s3.amazonaws.com/#{bucket}/#{blob.is_a?(String) ? blob : blob.key}" 7 | end 8 | 9 | def valid_image?(io) 10 | content_types = ActiveStorage::Variant::WEB_IMAGE_CONTENT_TYPES 11 | extensions = content_types.map { |ct| ct.gsub('image/', '') } 12 | submitted_extension = io.original_filename.split('.')[-1].downcase 13 | content_types.include?(io.content_type) && extensions.include?(submitted_extension) && 14 | extensions.map(&:to_sym).include?(FastImage.type(io)) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/helpers/users_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under UsersController. 2 | module UsersHelper 3 | def avatar_url(user, size = 16) 4 | user ||= current_user 5 | if user&.avatar&.attached? 6 | uploaded_url(user.avatar.blob.key) 7 | else 8 | "https://unicornify.pictures/avatar/#{user.id}?s=#{size}" 9 | end 10 | end 11 | 12 | def stack_oauth_url 13 | "https://stackoverflow.com/oauth?client_id=#{SiteSetting['SEApiClientId']}" \ 14 | "&scope=&redirect_uri=#{stack_redirect_url}" 15 | end 16 | 17 | def can_change_category(user, target) 18 | user.privilege?('flag_curate') && 19 | (user.is_moderator || user.is_admin || target.min_trust_level.nil? || target.min_trust_level <= user.trust_level) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/helpers/votes_helper.rb: -------------------------------------------------------------------------------- 1 | # Provides helper methods for use by views under VotesController. 2 | module VotesHelper 3 | end 4 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/mailers/.keep -------------------------------------------------------------------------------- /app/mailers/admin_mailer.rb: -------------------------------------------------------------------------------- 1 | class AdminMailer < ApplicationMailer 2 | default from: 'moderators-noreply@codidact.com' 3 | 4 | def to_moderators 5 | @subject = params[:subject] 6 | @body_markdown = params[:body_markdown] 7 | query = 'SELECT DISTINCT u.email FROM subscriptions s INNER JOIN users u ON s.user_id = u.id ' \ 8 | "INNER JOIN community_users cu ON cu.user_id = u.id WHERE s.type = 'moderators' AND " \ 9 | '(u.is_global_admin = 1 OR u.is_global_moderator = 1 OR cu.is_admin = 1 OR cu.is_moderator = 1)' 10 | emails = ActiveRecord::Base.connection.execute(query).to_a.flatten 11 | mail subject: "Codidact Moderators: #{@subject}", to: 'moderators-noreply@codidact.org', bcc: emails 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'noreply@codidact.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /app/mailers/two_factor_mailer.rb: -------------------------------------------------------------------------------- 1 | class TwoFactorMailer < ApplicationMailer 2 | default from: 'noreply@codidact.com' 3 | 4 | def disable_email 5 | user = params[:user] 6 | @host = params[:host] 7 | @token = SecureRandom.urlsafe_base64(64) 8 | user.update(login_token: @token, login_token_expires_at: 5.minutes.from_now) 9 | mail to: user.email, subject: 'Disable two-factor authentication on Codidact' 10 | end 11 | 12 | def login_email 13 | user = params[:user] 14 | @host = params[:host] 15 | @token = SecureRandom.urlsafe_base64(64) 16 | user.update(login_token: @token, login_token_expires_at: 5.minutes.from_now) 17 | mail to: user.email, subject: 'Your sign in link for Codidact' 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/models/.keep -------------------------------------------------------------------------------- /app/models/ability.rb: -------------------------------------------------------------------------------- 1 | class Ability < ApplicationRecord 2 | include CommunityRelated 3 | 4 | validates :internal_id, uniqueness: { scope: [:community_id] } 5 | 6 | def manual? 7 | post_score_threshold.nil? && edit_score_threshold.nil? && flag_score_threshold.nil? 8 | end 9 | 10 | def self.on_user(user) 11 | Ability.where(id: UserAbility.where(community_user: user.community_user).select(:ability_id).distinct) 12 | end 13 | 14 | def self.trust_levels 15 | { 16 | 0 => 'everyone', 17 | 1 => 'anyone with a user account', 18 | 2 => 'all but new users', 19 | 3 => 'veteran users', 20 | 4 => 'moderators only', 21 | 5 => 'staff only' 22 | } 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/models/ability_queue.rb: -------------------------------------------------------------------------------- 1 | class AbilityQueue < ApplicationRecord 2 | belongs_to :community_user 3 | scope :pending, -> { where(completed: false) } 4 | 5 | def self.add(user, comment) 6 | unless AbilityQueue.pending.where(community_user: user.community_user).any? 7 | AbilityQueue.create(community_user: user.community_user, comment: comment, completed: false) 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/answer.rb: -------------------------------------------------------------------------------- 1 | class Answer < Post 2 | default_scope { where(post_type_id: Answer.post_type_id) } 3 | 4 | def self.post_type_id 5 | PostType.mapping['Answer'] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/article.rb: -------------------------------------------------------------------------------- 1 | class Article < Post 2 | default_scope { where(post_type_id: Article.post_type_id) } 3 | 4 | def self.post_type_id 5 | PostType.mapping['Article'] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/audit_log.rb: -------------------------------------------------------------------------------- 1 | class AuditLog < ApplicationRecord 2 | include CommunityRelated 3 | 4 | belongs_to :related, polymorphic: true, optional: true 5 | belongs_to :user, optional: true 6 | 7 | class << self 8 | [:admin_audit, :moderator_audit, :action_audit, :user_annotation, :user_history, :block_log, 9 | :rate_limit_log].each do |log_type| 10 | define_method(log_type) do |**values| 11 | create(values.merge(log_type: log_type.to_s, community_id: RequestContext.community_id)) 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/models/blocked_item.rb: -------------------------------------------------------------------------------- 1 | class BlockedItem < ApplicationRecord 2 | scope :active, -> { where('expires IS NULL OR expires > NOW()') } 3 | 4 | # Allow for easy checking of type 5 | ['ip', 'email', 'email_host'].each do |bt| 6 | define_method "#{bt.underscore}?" do 7 | item_type == bt 8 | end 9 | scope "#{bt}s".to_sym, -> { active.where(item_type: bt) } 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/close_reason.rb: -------------------------------------------------------------------------------- 1 | class CloseReason < ApplicationRecord 2 | include MaybeCommunityRelated 3 | 4 | scope :active, -> { where(active: true) } 5 | 6 | validates :name, uniqueness: { scope: [:community_id] } 7 | end 8 | -------------------------------------------------------------------------------- /app/models/community.rb: -------------------------------------------------------------------------------- 1 | class Community < ApplicationRecord 2 | has_many :community_users 3 | 4 | validates :host, uniqueness: true 5 | end 6 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/concerns/community_related.rb: -------------------------------------------------------------------------------- 1 | module CommunityRelated 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | belongs_to :community 6 | default_scope { where(community_id: RequestContext.community_id) } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/concerns/maybe_community_related.rb: -------------------------------------------------------------------------------- 1 | module MaybeCommunityRelated 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | belongs_to :community, optional: true 6 | default_scope { where(community_id: RequestContext.community_id).or(where(community_id: nil)) } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/concerns/post_related.rb: -------------------------------------------------------------------------------- 1 | module PostRelated 2 | extend ActiveSupport::Concern 3 | include CommunityRelated 4 | 5 | included do 6 | belongs_to :post 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/error_log.rb: -------------------------------------------------------------------------------- 1 | class ErrorLog < ApplicationRecord 2 | belongs_to :community, optional: true 3 | belongs_to :user, optional: true 4 | end 5 | -------------------------------------------------------------------------------- /app/models/flag.rb: -------------------------------------------------------------------------------- 1 | # Represents a flag. Flags are attached to both a user and a post, and have a single status. 2 | class Flag < ApplicationRecord 3 | include PostRelated 4 | belongs_to :user 5 | belongs_to :handled_by, class_name: 'User', optional: true 6 | belongs_to :post_flag_type 7 | 8 | scope :handled, -> { where.not(status: nil) } 9 | scope :unhandled, -> { where(status: nil) } 10 | 11 | scope :confidential, -> { where(post_flag_type: PostFlagType.confidential).or(where(post_flag_type: nil)) } 12 | scope :not_confidential, -> { where(post_flag_type: PostFlagType.not_confidential) } 13 | end 14 | -------------------------------------------------------------------------------- /app/models/help_doc.rb: -------------------------------------------------------------------------------- 1 | class HelpDoc < Post 2 | def self.post_type_id 3 | PostType.mapping['HelpDoc'] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/models/license.rb: -------------------------------------------------------------------------------- 1 | class License < ApplicationRecord 2 | include CommunityRelated 3 | 4 | scope :enabled, -> { where(enabled: true) } 5 | scope :disabled, -> { where(enabled: false) } 6 | 7 | validates :name, uniqueness: { scope: [:community_id] } 8 | 9 | def self.default_order(category = nil) 10 | if category.present? 11 | License.all.order(Arel.sql(sanitize_sql_array(['id = ? DESC', category.license_id]))) 12 | .order(default: :desc) 13 | else 14 | License.all.order(default: :desc) 15 | end.order(name: :asc) 16 | end 17 | 18 | def self.site_default 19 | License.where(default: true).first 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/models/mod_warning.rb: -------------------------------------------------------------------------------- 1 | class ModWarning < ApplicationRecord 2 | # Warning class name not accepted by Rails, hence this needed 3 | self.table_name = 'warnings' 4 | 5 | belongs_to :community_user 6 | belongs_to :author, class_name: 'User' 7 | 8 | def suspension_active? 9 | active && is_suspension && !suspension_end.past? 10 | end 11 | 12 | def body_as_html 13 | ApplicationController.helpers.render_markdown(body) 14 | end 15 | 16 | # These two are neccessary for the new warning form to work. 17 | def suspension_duration 18 | 1 19 | end 20 | 21 | def suspension_public_notice 22 | nil 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/models/notification.rb: -------------------------------------------------------------------------------- 1 | class Notification < ApplicationRecord 2 | include CommunityRelated 3 | belongs_to :user 4 | 5 | delegate :name, to: :community, prefix: true 6 | end 7 | -------------------------------------------------------------------------------- /app/models/pinned_link.rb: -------------------------------------------------------------------------------- 1 | class PinnedLink < ApplicationRecord 2 | include MaybeCommunityRelated 3 | belongs_to :post 4 | end 5 | -------------------------------------------------------------------------------- /app/models/policy_doc.rb: -------------------------------------------------------------------------------- 1 | class PolicyDoc < Post 2 | def self.post_type_id 3 | PostType.mapping['PolicyDoc'] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/models/post_flag_type.rb: -------------------------------------------------------------------------------- 1 | class PostFlagType < ApplicationRecord 2 | include CommunityRelated 3 | 4 | validates :name, uniqueness: { scope: [:community_id] } 5 | 6 | scope :not_confidential, -> { where(confidential: false) } 7 | scope :confidential, -> { where(confidential: true) } 8 | end 9 | -------------------------------------------------------------------------------- /app/models/post_history_tag.rb: -------------------------------------------------------------------------------- 1 | class PostHistoryTag < ApplicationRecord 2 | belongs_to :post_history 3 | belongs_to :tag 4 | 5 | validates :relationship, uniqueness: { scope: [:tag_id, :post_history_id] } 6 | end 7 | -------------------------------------------------------------------------------- /app/models/post_history_type.rb: -------------------------------------------------------------------------------- 1 | class PostHistoryType < ApplicationRecord 2 | has_many :post_histories 3 | 4 | validates :name, uniqueness: true 5 | end 6 | -------------------------------------------------------------------------------- /app/models/post_type.rb: -------------------------------------------------------------------------------- 1 | class PostType < ApplicationRecord 2 | has_many :posts 3 | has_and_belongs_to_many :categories 4 | 5 | validates :name, uniqueness: true 6 | 7 | def self.mapping 8 | Rails.cache.fetch 'post_type_ids' do 9 | PostType.all.map { |pt| [pt.name, pt.id] }.to_h 10 | end 11 | end 12 | 13 | def self.[](key) 14 | PostType.find_by(name: key) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/models/question.rb: -------------------------------------------------------------------------------- 1 | class Question < Post 2 | default_scope { where(post_type_id: Question.post_type_id) } 3 | 4 | scope :meta, -> { joins(:category).where(categories: { name: 'Meta' }) } 5 | scope :main, -> { joins(:category).where(categories: { name: 'Main' }) } 6 | 7 | def self.post_type_id 8 | PostType.mapping['Question'] 9 | end 10 | 11 | def answers 12 | Answer.where(parent: self) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/models/tag_set.rb: -------------------------------------------------------------------------------- 1 | class TagSet < ApplicationRecord 2 | include CommunityRelated 3 | has_many :tags 4 | has_many :tags_with_paths, class_name: 'TagWithPath' 5 | has_many :categories 6 | 7 | validates :name, uniqueness: { scope: [:community_id] }, presence: true 8 | 9 | def self.meta 10 | where(name: 'Meta').first 11 | end 12 | 13 | def self.main 14 | where(name: 'Main').first 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/models/tag_with_path.rb: -------------------------------------------------------------------------------- 1 | class TagWithPath < Tag 2 | self.table_name = 'tags_paths' 3 | end 4 | -------------------------------------------------------------------------------- /app/models/user_ability.rb: -------------------------------------------------------------------------------- 1 | class UserAbility < ApplicationRecord 2 | belongs_to :community_user 3 | belongs_to :ability 4 | 5 | def suspended? 6 | return true if is_suspended && suspension_end.nil? # permanent suspension 7 | return true if is_suspended && !suspension_end.past? 8 | 9 | if is_suspended 10 | update(is_suspended: false, suspension_message: nil, suspension_end: nil) 11 | end 12 | 13 | false 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/models/warning_template.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | 3 | class WarningTemplate < ApplicationRecord 4 | include CommunityRelated 5 | 6 | validates :name, uniqueness: { scope: [:community_id] } 7 | 8 | def body_as_b64 9 | body_with_site_replacements = body.gsub '$SiteName', SiteSetting['SiteName'] 10 | 11 | chat_link = if SiteSetting['ChatLink'].nil? 12 | 'chat' 13 | else 14 | "[chat](#{SiteSetting['ChatLink']})" 15 | end 16 | body_with_site_replacements = body_with_site_replacements.gsub '$ChatLink', chat_link 17 | 18 | Base64.encode64(body_with_site_replacements) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/views/admin/admin_email.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'posts/markdown_script' %> 2 | 3 |

<%= t 'admin.tools.email_moderators' %>

4 |

<%= t 'admin.email_moderators_blurb' %>

5 | 6 | <%= form_with url: send_moderator_email_path do |f| %> 7 |
8 | <%= f.label :subject, t('g.subject').capitalize, class: 'form-element' %> 9 | <%= f.text_field :subject, class: 'form-element' %> 10 |
11 | 12 | <%= render 'shared/body_field', f: f, field_name: :body_markdown, field_label: t('g.body').capitalize, post: nil %> 13 | 14 |
15 | 16 | <%= f.submit t('g.send').capitalize, class: 'button is-filled' %> 17 | <% end %> -------------------------------------------------------------------------------- /app/views/admin/error_reports.html.erb: -------------------------------------------------------------------------------- 1 |

<%= t 'admin.tools.error_reports' %>

2 |

<%= pluralize(@reports.count, t('g.error')) %> <%= t 'g.logged' %>

3 | 4 | <%= form_tag admin_error_reports_path, method: :get, class: 'has-margin-bottom-4' do %> 5 | <%= label_tag :uuid, t('admin.error_search_uuid') %> 6 | <%= text_field_tag :uuid, params[:uuid], class: 'form-element', placeholder: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' %> 7 | <%= submit_tag t('g.search').capitalize, class: 'button is-filled' %> 8 | <% end %> 9 | 10 | <% @reports.each do |report| %> 11 | <%= render 'error_report', report: report %> 12 | <% end %> 13 | 14 | <%= will_paginate @reports, renderer: BootstrapPagination::Rails %> -------------------------------------------------------------------------------- /app/views/admin_mailer/to_moderators.html.erb: -------------------------------------------------------------------------------- 1 | <%= raw(sanitize(ApplicationController.helpers.render_markdown(@body_markdown), 2 | scrubber: ApplicationController.helpers.scrubber)) %> -------------------------------------------------------------------------------- /app/views/admin_mailer/to_moderators.text.erb: -------------------------------------------------------------------------------- 1 | <%= ApplicationController.helpers.strip_markdown @body_markdown %> -------------------------------------------------------------------------------- /app/views/application/keyboard_tools.html.erb: -------------------------------------------------------------------------------- 1 |

Keyboard tools

2 |

Codidact supports keyboard tools to enhance user accessibility. You can activate (and then later deactivate) them here on this page:

3 |

You'll need JavaScript to be enabled for the tools to work.

4 | 5 |

Keyboard tools are currently unknown. 6 | 7 |

8 | 9 |

This setting is stored in your browser and not your user account, so you can set it as you want it on any device.

-------------------------------------------------------------------------------- /app/views/categories/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit Category

2 |

3 | If you need to change something about one of your site's categories, this is the place to do it. 4 |

5 | 6 | <%= render 'form', submit_path: update_category_path(@category) %> -------------------------------------------------------------------------------- /app/views/categories/new.html.erb: -------------------------------------------------------------------------------- 1 |

New Category

2 |

3 | If the standard two Q&A categories aren't enough for your site, you can add a new category here. 4 |

5 | 6 | <%= render 'form', submit_path: create_category_path %> 7 | -------------------------------------------------------------------------------- /app/views/categories/post_types.html.erb: -------------------------------------------------------------------------------- 1 |

What kind of post?

2 |

3 | This category has more than one type of post available. Pick a post type to get started. 4 |

5 | 6 | <% @post_types.each do |pt| %> 7 |

<%= link_to pt.name.underscore.humanize, new_category_post_path(post_type: pt, category: @category) %>

8 |

<%= pt.description %>

9 |
10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/comments/post.html.erb: -------------------------------------------------------------------------------- 1 | <% @comments.each do |comment| %> 2 | <%= render 'comment', comment: comment %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/custom_sessions/verify_2fa.html.erb: -------------------------------------------------------------------------------- 1 |

Two-factor authentication

2 |

3 | Your account has two-factor authentication enabled. Enter a code from your authenticator app here. 4 |

5 | 6 | <%= form_tag login_verify_code_path do %> 7 | <%= hidden_field_tag 'uid', params[:uid] %> 8 | 9 |
10 | <%= label_tag 'code', 'Code', class: 'form-element' %> 11 | <%= text_field_tag 'code', '', class: 'form-element' %> 12 |
13 | 14 |
15 | <%= submit_tag 'Verify', class: 'button is-filled' %> 16 |
17 | <% end %> -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend confirmation instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= render "devise/shared/error_messages", resource: resource %> 5 | 6 |
7 | <%= f.label :email, class: "form-element" %> 8 | <%= f.email_field :email, class: 'form-element', autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %> 9 |
10 | 11 | <%= f.submit "Resend confirmation instructions", class: 'button is-filled is-very-large' %> 12 | <% end %>
13 | 14 | <%= render "devise/shared/links" %> 15 | -------------------------------------------------------------------------------- /app/views/devise/mailer/_friendly_footer.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Thanks!

3 |

Your Friendly Neighbourhood Codidactyl

-------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome to Codidact, <%= @resource.username %>! We're glad you're here.

2 | 3 |

Please confirm your registration by clicking below (or copy and paste the URL into your browser).

4 | 5 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token), class: 'button is-filled' %>

6 | 7 |

<%= confirmation_url(@resource, confirmation_token: @token) %>

8 | 9 | <%= render 'devise/mailer/friendly_footer' %> 10 | -------------------------------------------------------------------------------- /app/views/devise/mailer/password_change.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.username %>!

2 | 3 |

4 | This email is just to let you know that your password has been changed. 5 |

6 |

7 | If this was you, you can safely ignore this email. If it wasn't, please 8 | <%= link_to 'change your password now', new_password_url(@resource) %> to protect your account. 9 |

10 | 11 | <%= render 'devise/mailer/friendly_footer' %> 12 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.username %>!

2 | 3 |

Someone has requested a link to change your password. You can do this through the link below.

4 | 5 |

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token), class: 'button is-filled' %>

6 | 7 |

8 | If you didn't request this, please ignore this email—your password won't be changed until you follow the link 9 | above and set a new password. 10 |

11 | 12 | <%= render 'devise/mailer/friendly_footer' %> 13 | -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.username %>!

2 | 3 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

4 | 5 |

Click the link below to unlock your account:

6 | 7 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token), class: 'button is-filled' %>

8 | 9 | <%= render 'devise/mailer/friendly_footer' %> 10 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.erb: -------------------------------------------------------------------------------- 1 |

Forgot your password?

2 | 3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= render "devise/shared/error_messages", resource: resource %> 5 | 6 |
7 | <%= f.label :email, class: "form-element" %> 8 | <%= f.email_field :email, class: 'form-element', autofocus: true, autocomplete: "email" %> 9 |
10 | 11 | <%= f.submit "Send me reset password instructions", class: 'button is-filled is-very-large' %> 12 | <% end %>
13 | 14 | <%= render "devise/shared/links" %> 15 | -------------------------------------------------------------------------------- /app/views/devise/shared/_error_messages.html.erb: -------------------------------------------------------------------------------- 1 | <% if resource.errors.any? %> 2 |
3 |

4 | <%= I18n.t("errors.messages.not_saved", 5 | count: resource.errors.count, 6 | resource: resource.class.model_name.human.downcase) 7 | %> 8 |

9 | 14 |
15 | <% end %>
16 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend unlock instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= render "devise/shared/error_messages", resource: resource %> 5 | 6 |
7 | <%= f.label :email, class: "form-element" %> 8 | <%= f.email_field :email, class: 'form-element', autofocus: true, autocomplete: "email" %> 9 |
10 | 11 | <%= f.submit "Resend unlock instructions", class: 'button is-filled is-very-large' %> 12 | <% end %>
13 | 14 | <%= render "devise/shared/links" %> 15 | -------------------------------------------------------------------------------- /app/views/errors/conflict.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Conflict' %> 2 | 3 |

409

4 |

conflict

5 | 6 |

Your request conflicted with another request.

7 | 8 |

Any changes you were trying to make are unlikely to have been saved - go back and try again.

9 | 10 | 11 |

12 | <%= link_to 'Go back', :back, class: 'button is-outlined' %> 13 | <%= link_to 'Go home', root_path, class: 'button is-outlined' %> 14 |

-------------------------------------------------------------------------------- /app/views/errors/error.html.erb: -------------------------------------------------------------------------------- 1 |

Error

-------------------------------------------------------------------------------- /app/views/errors/forbidden.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Forbidden' %> 2 | 3 |

403

4 |

forbidden

5 | 6 |

You don't have the necessary permissions to do that.

7 | 8 |

You might have tried to access or change something you don't have access to.

9 | 10 | 11 |

12 | <%= link_to 'Go back', :back, class: 'button is-outlined' %> 13 | <%= link_to 'Go home', root_path, class: 'button is-outlined' %> 14 |

-------------------------------------------------------------------------------- /app/views/errors/locked.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Locked' %> 2 | 3 |

401

4 |

locked

5 | 6 |

The post has been locked and cannot be edited, commented or voted on.

7 | 8 |

9 | <%= link_to 'Go back', :back, class: 'button is-outlined' %> 10 | <%= link_to 'Go home', root_path, class: 'button is-outlined' %> 11 |

-------------------------------------------------------------------------------- /app/views/errors/not_found.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Not Found' %> 2 | 3 |

404

4 |

not found

5 | 6 |

The page you're looking for couldn't be found.

7 | 8 |

You might have followed an old link, or a post might have been deleted.

9 | 10 | 11 |

12 | <%= link_to 'Go back', :back, class: 'button is-outlined' %> 13 | <%= link_to 'Go home', root_path, class: 'button is-outlined' %> 14 |

-------------------------------------------------------------------------------- /app/views/errors/stat.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Stat Error' %> 2 | 3 |

418

4 |

stat error

5 | 6 |

<%= ApplicationRecord.useful_err_msg.sample %>

-------------------------------------------------------------------------------- /app/views/errors/unprocessable_entity.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Unprocessable Entity' %> 2 | 3 |

422

4 |

unprocessable

5 | 6 |

Your request couldn't be processed.

7 | 8 |

9 | Our server's sulking today. Log out and back in, and if this keeps happening, let us know 10 | on Meta. 11 |

12 | 13 | 14 |

15 | <%= link_to 'Go back', :back, class: 'button is-outlined' %> 16 | <%= link_to 'Go home', root_path, class: 'button is-outlined' %> 17 |

-------------------------------------------------------------------------------- /app/views/flags/handled.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "Handled Moderator Flags" %> 2 | 3 |

Handled Flags

4 |

The following list contains flags that have already been handled. You can't change the outcome of these any more.

5 | 6 |
7 | <%= link_to 'Active', flag_queue_path, class: 'button is-muted is-outlined' %> 8 | <%= link_to 'Handled', handled_flags_path, class: 'button is-muted is-outlined is-active' %> 9 |
10 | 11 | <% @flags.each do |flag| %> 12 | <%= render 'handled', flag: flag %> 13 | <% end %> -------------------------------------------------------------------------------- /app/views/flags/history.html.erb: -------------------------------------------------------------------------------- 1 |

Flag History

2 |

3 | Below is a list of all the flags you have cast and the outcome of each of them. Moderators handling your flags may also 4 | have left you feedback. 5 |

6 | 7 |

8 | <%= pluralize(@flags.count, 'flag') %> 9 |

10 |

<%= @statuses.map { |s, c| "#{c} #{s.present? ? s : 'pending'}" }.join(', ') %>

11 | 12 | <% @flags.each do |flag| %> 13 | <%= render 'handled', flag: flag %> 14 | <% end %> 15 | 16 | <%= will_paginate @flags, renderer: BootstrapPagination::Rails %> 17 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 25 | 26 | 27 | 28 | <%= yield %> 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/licenses/_license.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | <%= license.name %> 5 | <% if license.default? %> 6 | default 7 | <% end %> 8 | <% unless license.enabled? %> 9 | 10 | Disabled 11 | 12 | <% end %> 13 |

14 |

<%= link_to license.url %>

15 |

16 | <%= link_to 'Edit', edit_license_path(license), class: 'button is-outlined' %> 17 | <%= link_to license.enabled? ? 'Disable' : 'Enable', toggle_license_path(license), class: 'button is-outlined', 18 | method: :post %> 19 |

20 |
21 |
-------------------------------------------------------------------------------- /app/views/licenses/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit License

2 |

If you've made a mistake or something's changed, you can update license details here.

3 | 4 | <%= render 'form', submit_path: update_license_path(@license) %> -------------------------------------------------------------------------------- /app/views/licenses/new.html.erb: -------------------------------------------------------------------------------- 1 |

New License

2 |

You can add a new license for users to pick from here.

3 | 4 | <%= render 'form', submit_path: new_license_path %> -------------------------------------------------------------------------------- /app/views/moderator/recent_comments.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Recent Comments' %> 2 | 3 |

Recent Comments

4 |

5 | This is a log of all comments posted recently on this site. This may not be very useful on higher-traffic 6 | sites; consider using activity logs on user profiles instead. 7 |

8 | 9 | <% @comments.each do |comment| %> 10 | <%= render 'comments/comment', comment: comment, with_post_link: true %> 11 | <% end %> 12 | 13 |
14 | <%= will_paginate @comments, renderer: BootstrapPagination::Rails %> 15 |
16 | -------------------------------------------------------------------------------- /app/views/moderator/recently_deleted_posts.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "Recently Deleted Posts" %> 2 | 3 |

Recently Deleted Posts

4 |
5 | <% @posts.each do |post| %> 6 | <%= render 'posts/type_agnostic', post: post %> 7 | <% end %> 8 |
9 | 10 | <%= will_paginate @posts, renderer: BootstrapPagination::Rails %> 11 | -------------------------------------------------------------------------------- /app/views/notifications/index.erb: -------------------------------------------------------------------------------- 1 |

Your Inbox

2 |

You'll find all your inbox messages here, as far back as your account goes.

3 | 4 | <% @notifications.each do |notif| %> 5 |
6 |
<%= CGI.unescape_html(notif.created_at.strftime('%b %-d, %Y at %H:%M')).html_safe %>
7 | <%= notif.content %> 8 |
9 | <% end %> 10 | 11 | <%= will_paginate @notifications, renderer: BootstrapPagination::Rails %> 12 | -------------------------------------------------------------------------------- /app/views/pinned_links/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit featured link

2 | 3 | <% if @link.errors.any? %> 4 |
5 | These errors prevented this link being saved: 6 | 11 |
12 | <% end %> 13 | 14 | <%= render 'form', url: update_pinned_link_path(global: params[:global]) %> 15 | -------------------------------------------------------------------------------- /app/views/pinned_links/new.html.erb: -------------------------------------------------------------------------------- 1 |

New featured link

2 | 3 | <% if @link.errors.any? %> 4 |
5 | These errors prevented this link being saved: 6 | 11 |
12 | <% end %> 13 | 14 | <%= render 'form', url: create_pinned_link_path %> -------------------------------------------------------------------------------- /app/views/posts/_markdown_script.html.erb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/views/posts/_mdhint.html.erb: -------------------------------------------------------------------------------- 1 |
2 | We support Markdown for posts: 3 | **bold**, *italics*, `code`, two newlines for paragraphs 4 |
5 | -------------------------------------------------------------------------------- /app/views/posts/_type_agnostic.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | post_types_views = { 3 | 'Question' => 'posts/list', 4 | 'Answer' => 'posts/list', 5 | 'PolicyDoc' => 'posts/document', 6 | 'HelpDoc' => 'posts/document', 7 | 'Article' => 'posts/article_list' 8 | } 9 | %> 10 | <% @show_type_tag = !!defined?(show_type_tag) ? show_type_tag : false %> 11 | <% @show_category_tag = !!defined?(show_category_tag) ? show_category_tag : false %> 12 | <% @last_activity = !!defined?(last_activity) ? last_activity : true %> 13 | <%= render post_types_views[post.post_type.name], post: post, show_type_tag: @show_type_tag, 14 | show_category_tag: @show_category_tag, last_activity: @last_activity %> -------------------------------------------------------------------------------- /app/views/posts/help_center.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Help Center' %> 2 | 3 |

Help Center

4 | 5 |
6 |
7 |

Help

8 | <%= render 'help_center_posts', posts: @posts[HelpDoc.post_type_id] %> 9 |
10 | 11 |
12 |

Policy

13 | <%= render 'help_center_posts', posts: @posts[PolicyDoc.post_type_id] %> 14 |
15 |
16 | -------------------------------------------------------------------------------- /app/views/questions/lottery.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, 'Questions Lottery' %> 2 | 3 |

Questions

4 | 5 | <%= render 'list' %> 6 | -------------------------------------------------------------------------------- /app/views/reports/posts.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'tabs' %> 2 | 3 |
4 | <%= stat_panel 'questions', @questions.count %> 5 | <%= stat_panel 'answers', @answers.count %> 6 | <%= stat_panel 'comments', @comments.count %> 7 | <%= stat_panel 'posts this month', @this_month.count %> 8 |
9 | 10 |

New posts

11 | <%= line_chart [ 12 | { name: 'Questions', data: @questions.group_by_week(:created_at).count }, 13 | { name: 'Answers', data: @answers.group_by_week(:created_at).count }, 14 | { name: 'Comments', data: @comments.group_by_week(:created_at).count }, 15 | ] %> -------------------------------------------------------------------------------- /app/views/reports/subscriptions.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'tabs' %> 2 | 3 |
4 | <%= stat_panel 'all', @types.map { |_, v| v }.sum %> 5 | <%= stat_panel 'interesting', @types['interesting'] %> 6 | <%= stat_panel 'tag', @types['tag'] %> 7 | <%= stat_panel 'user', @types['user'] %> 8 |
9 | 10 |

New subscriptions

11 | <%= line_chart Subscription.where('created_at >= ?', 1.year.ago).group_by_week(:created_at).count %> -------------------------------------------------------------------------------- /app/views/reports/users.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'tabs' %> 2 | 3 |
4 | <%= stat_panel 'users', number_to_human(@users_all.count, format: '%n%u', units: { thousand: 'k', million: 'M' }) %> 5 | 6 | <%= stat_panel 'native signups', 7 | number_to_human(@users.count, format: '%n%u', units: { thousand: 'k', million: 'M' }) %> 8 | 9 | <%= stat_panel 'from se', 10 | number_to_human(@users_se.count, format: '%n%u', units: { thousand: 'k', million: 'M' }) %> 11 | 12 | <%= stat_panel 'this month', 13 | number_to_human(@users.where('users.created_at >= ?', 1.month.ago).count, format: '%n%u', units: { thousand: 'k', million: 'M' }) %> 14 |
15 | 16 |

New signups

17 | <%= line_chart @users.group_by_week(:created_at).count %> -------------------------------------------------------------------------------- /app/views/subscriptions/error.html.erb: -------------------------------------------------------------------------------- 1 |

New Questions Subscription

2 |
3 |

4 | There was a problem saving your subscription: 5 | 6 |

11 |

12 | 13 |

If you came here from a link and had filled in the requested details, this may be a bug. Please let us know on 14 | <%= link_to 'Meta', 'https://meta.codidact.com/' %>.

15 |
16 | -------------------------------------------------------------------------------- /app/views/subscriptions/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'users/tabs', user: current_user %> 2 | 3 |

Your Subscriptions

4 |

These are all the email subscriptions you're currently signed up for. You can turn them off or remove them entirely from here.

5 | 6 | <% @subscriptions.each do |sub| %> 7 |
8 | <%= sub.name %> 9 |

Subscription to <%= phrase_for sub.type, sub.qualifier %>, emailed every <%= pluralize(sub.frequency, 'day') %>.

10 | <%= check_box_tag :enabled, 1, sub.enabled, class: 'js-enable-subscription' %> 11 | <%= label_tag :enabled, 'Enabled?' %> · 12 | Remove 13 |
14 | <% end %> -------------------------------------------------------------------------------- /app/views/tags/_list.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% required_ids = @category&.required_tag_ids %> 3 | <% moderator_ids = @category&.moderator_tag_ids %> 4 | <% topic_ids = @category&.topic_tag_ids %> 5 | 6 | <% ApplicationRecord.with_lax_group_rules do %> 7 | <% @tags.each do |tag| %> 8 | <% required = required_ids&.include?(tag.id) ? 'is-filled' : '' %> 9 | <% topic = topic_ids&.include?(tag.id) ? 'is-outlined' : '' %> 10 | <% moderator = moderator_ids&.include?(tag.id) ? 'is-red is-outlined' : '' %> 11 | <% classes = "badge is-tag #{required} #{topic} #{moderator}" %> 12 | <%= render 'tag', category: @category, tag: tag, classes: classes %> 13 | <% end %> 14 | <% end %> 15 |
-------------------------------------------------------------------------------- /app/views/tour/end.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | Codidactyl 4 |
5 |
6 |
7 |
8 |

Congratulations!

9 |

You have successfully completed my tutorial. Now you're ready to dive into this community. Go and learn together.

10 |
11 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /app/views/tour/question1.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | Codidactyl 4 |
5 |
6 |
7 |
8 |

Great.

9 |

This is a Q&A site, so everything starts with a question. Let's try to ask one to see, how it works.

10 |
11 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /app/views/two_factor/disable_code.html.erb: -------------------------------------------------------------------------------- 1 |

Confirm your code

2 |

Last step: to confirm that it's really you trying to remove security from your account, enter the code shown in your 3 | authenticator app.

4 | 5 | <%= form_tag two_factor_confirm_disable_path do %> 6 |
7 | <%= label_tag 'code', 'Code', class: 'form-element' %> 8 | <%= text_field_tag 'code', '', class: 'form-element' %> 9 |
10 | 11 | <%= submit_tag 'Confirm', class: 'button is-filled' %> 12 | <% end %> -------------------------------------------------------------------------------- /app/views/two_factor/disable_link.html.erb: -------------------------------------------------------------------------------- 1 |

Disabling two-factor authentication

2 | 3 |

Please click the button below to confirm you want to disable two-factor authentication on your account.

4 | 5 |

<%= link_to 'Disable 2FA', two_factor_confirm_disable_link_path, method: :post, class: 'button is-filled is-danger' %>

-------------------------------------------------------------------------------- /app/views/two_factor/enable_2fa.html.erb: -------------------------------------------------------------------------------- 1 |

Add Codidact to your authenticator

2 |

3 | Your account has been set up with the necessary credentials to use 2FA. You now need to add your account to 4 | your mobile authenticator. Scan the QR code below with your authenticator app and you should be set to go. 5 |

6 | 7 |
8 | 9 | <%= link_to 'Done, next step', two_factor_enable_code_path, class: 'button is-filled' %> -------------------------------------------------------------------------------- /app/views/two_factor/enable_code.html.erb: -------------------------------------------------------------------------------- 1 |

Confirm your code

2 |

Last step: to confirm that you're all correctly set up, enter the code shown in your mobile authenticator below.

3 | 4 | <%= form_tag two_factor_confirm_enable_path do %> 5 |
6 | <%= label_tag 'code', 'Code', class: 'form-element' %> 7 | <%= text_field_tag 'code', '', class: 'form-element' %> 8 |
9 | 10 | <%= submit_tag 'Confirm', class: 'button is-filled' %> 11 | <% end %> -------------------------------------------------------------------------------- /app/views/two_factor_mailer/disable_email.html.erb: -------------------------------------------------------------------------------- 1 |

Disable two-factor authentication

2 |

3 | Someone recently requested a link to turn off two-factor authentication on your Codidact account. 4 | If that was you, great! <%= link_to 'Use this link to disable 2FA', two_factor_disable_link_url(@token, host: @host) %> 5 |

6 | 7 |

If this wasn't you, you should <%= link_to 'change your password', edit_user_registration_url(host: @host) %>

-------------------------------------------------------------------------------- /app/views/two_factor_mailer/disable_email.text.erb: -------------------------------------------------------------------------------- 1 | ### Disable two-factor authentication ### 2 | 3 | Someone recently requested a link to turn off two-factor authentication on your Codidact account. 4 | If that was you, great! Use this link to disable 2FA: <%= two_factor_disable_link_url(@token, host: @host) %> 5 | 6 | If this wasn't you, you should change your password: <%= edit_user_registration_url(host: @host) %> -------------------------------------------------------------------------------- /app/views/two_factor_mailer/login_email.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome back to Codidact!

2 |

<%= link_to 'Use this link to sign in', qr_login_url(@token, host: @host) %>

3 |

We'll see you soon!

-------------------------------------------------------------------------------- /app/views/two_factor_mailer/login_email.text.erb: -------------------------------------------------------------------------------- 1 | ### Welcome back to Codidact! ### 2 | 3 | Use this link to sign in: <%= qr_login_url(@token, host: @host) %> 4 | 5 | We'll see you soon! -------------------------------------------------------------------------------- /app/views/users/_post_usercard.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
<%= time_ago_in_words(post.created_at) %> ago
3 |
4 | user avatar 5 |
6 | <%= link_to user_path(post.user), dir: 'ltr' do %> 7 | <%= post.user.rtl_safe_username %> 8 | <% end %> 9 | <%= post.user.reputation %> 10 |
11 |
12 |
13 |
-------------------------------------------------------------------------------- /app/views/users/posts.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title, "Posts by #{@user.rtl_safe_username}" %> 2 | 3 |

Posts by <%= link_to @user.rtl_safe_username, user_path(@user), dir: 'ltr'%>

4 | 5 |
6 | <%= link_to 'Score', query_url(sort: 'score'), class: "button is-muted is-outlined " + (active_search?('score') ? "is-active" : "") %> 7 | <%= link_to 'Age', query_url(sort: 'age'), class: "button is-muted is-outlined " + (active_search?('age') ? "is-active" : "") %> 8 |
9 | 10 |
11 | <% @posts.each do |post| %> 12 | <%= render 'posts/type_agnostic', post: post, show_type_tag: true, show_category_tag: true %> 13 | <% end %> 14 |
15 | 16 | <%= will_paginate @posts, renderer: BootstrapPagination::Rails %> -------------------------------------------------------------------------------- /app/views/users/qr_login_code.html.erb: -------------------------------------------------------------------------------- 1 |

Mobile Sign In

2 |

3 | Passwords too much effort? Use a QR code scanning app to scan this code on your device and 4 | follow the URL to log in there. 5 |

6 | 7 |
8 | 9 | <%= raw(@qr_code.as_svg(standalone: false, module_size: 4)) %> 10 | 11 |
-------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | APP_PATH = File.expand_path('../../config/application', __FILE__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require_relative '../config/boot' 8 | require 'rake' 9 | Rake.application.run 10 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) 11 | Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } 12 | gem 'spring', match[1] 13 | require 'spring/binstub' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('config/environment', __dir__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | DFhXs7S5cE7flrLRj7ZJITW35yeONO0KtOl8q+tCzHqM64hwLgv+JYel4p27a7N1lECfN8uzpqfebILChsPx7q2p6OohnwVvJ2AjT7iYD6LLOuL71tgBOqRNvEZpYd8qozEjx/JwD/uUNwhROmrqex//yihtc0KpTrpiDu5weRrDZ7lW1eYtHyvLK2Ca4GmdYkn+eeQ2bJN1jR+PHNABtKdTKvTsoH0/RkoN0Gn2fCRqoRO3k1XGsV0djpzMsQxVJPFkBLG8P1tUbdnCp8XgbRluwkg1tCcV4eluIYgR3leLsLvTp4TtJ4oOC1HlJlO+vJIvTEub--E50Dib4ZMCNxssp1--W8wY+Xwkz3LOdwY+rESL/g== -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/initializers/amazon_ses.rb: -------------------------------------------------------------------------------- 1 | ActionMailer::Base.add_delivery_method :ses, AWS::SES::Base, 2 | access_key_id: Rails.application.credentials.ses_access_key, 3 | secret_access_key: Rails.application.credentials.ses_secret_key, 4 | server: 'email.us-east-1.amazonaws.com' -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | if Rails.env.production? 4 | Rails.application.config.session_store :cookie_store, key: 'codidact_acct', domain: :all 5 | else 6 | Rails.application.config.session_store :cookie_store, key: 'codidact_acct' 7 | end 8 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/initializers/zz_cache_setup.rb: -------------------------------------------------------------------------------- 1 | Rails.cache.persistent 'current_commit', clear: true do 2 | [`git rev-parse HEAD`.strip, `git log -1 --date=iso --pretty=format:%cd`.strip] 3 | end 4 | -------------------------------------------------------------------------------- /config/initializers/zz_codidact_sites.rb: -------------------------------------------------------------------------------- 1 | Rails.cache.persistent 'codidact_sites', clear: true do 2 | # Do not show codidact_sites for development 3 | # (allows offline dev) 4 | if Rails.env.development? 5 | [] 6 | else 7 | response = Net::HTTP.get_response(URI('https://codidact.com/communities.json')) 8 | if response.code == '200' 9 | JSON.parse(response.body) 10 | else 11 | Rails.logger.fatal "Couldn't fetch Codidact sites: response code #{response.code}" 12 | exit 255 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /config/locales/es.yml: -------------------------------------------------------------------------------- 1 | es: 2 | hello: "Hola mundo" 3 | -------------------------------------------------------------------------------- /config/locales/strings/en.ads.yml: -------------------------------------------------------------------------------- 1 | en: 2 | ads: 3 | advertisements: 'advertisements' 4 | blurb_index: > 5 | You can, if you want, advertise this Codidact community on your personal homepage or on other sites 6 | (with the permission of the providers!) 7 | blurb_types: > 8 | There are three available ad types: 9 | image_link: 'Image link' 10 | image_html: 'Image HTML' 11 | random_posts: 'Random posts' 12 | specific_post: 'Specific post' 13 | random_from_cat: 'Random from Category' 14 | replace_x: 15 | post: 'Replace X with the post ID' 16 | category: 'Replace X with the category ID' 17 | -------------------------------------------------------------------------------- /config/locales/strings/en.g.yml: -------------------------------------------------------------------------------- 1 | en: 2 | g: 3 | # Alphabetical order please! 4 | at: 'at' 5 | body: 'body' 6 | codidact_network: 'codidact network' 7 | comment: 'comment' 8 | community: 'community' 9 | created: 'created' 10 | error: 'error' 11 | event: 'event' 12 | log: 'log' 13 | logged: 'logged' 14 | name: 'name' 15 | privilege: 'privilege' 16 | related: 'related' 17 | reputation: 'reputation' 18 | search: 'search' 19 | send: 'send' 20 | subject: 'subject' 21 | threshold: 'threshold' 22 | type: 'type' 23 | user: 'user' -------------------------------------------------------------------------------- /config/locales/strings/en.posts.yml: -------------------------------------------------------------------------------- 1 | en: 2 | posts: 3 | category_low_trust_level: > 4 | You don't have a high enough trust level to post in the :name category. 5 | type_requires_category: > 6 | You can't create a :type without a category. 7 | type_requires_parent: > 8 | You can't create a :type without a parent post. 9 | not_public_editable: > 10 | This type of post can only be edited by its author and the site moderators. -------------------------------------------------------------------------------- /config/locales/strings/en.rate_limit.yml: -------------------------------------------------------------------------------- 1 | rate_limit: 2 | new_user_posts: > 3 | You may only post :count :level posts per day. Once you have some well-received posts, your limit will increase. 4 | posts: > 5 | You may only post :count :level posts per day. 6 | new_user_suggested_edits: > 7 | You may only suggest :count edits per day. Once you have some well-received contributions, your limit will increase. 8 | suggested_edits: > 9 | You may only suggest :count edits per day. Once you have enough well-received suggestions, you will earn the ability 10 | to edit without review. -------------------------------------------------------------------------------- /config/locales/strings/es.ads.yml: -------------------------------------------------------------------------------- 1 | es: 2 | ads: 3 | advertisements: 'anuncios' 4 | blurb_index: > 5 | # es_ES 6 | Puedes, si quieres, anunciar esta comunidad Codidact en tu página web personal o en otros sitios 7 | (¡con el permiso de los proveedores!) 8 | blurb_types: > 9 | Hay tres tipos de anuncio disponibles: 10 | image_link: 'Enlace a la imagen' 11 | image_html: 'HTML de la imagen' 12 | random_posts: 'Entradas aleatorias' 13 | specific_post: 'Entrada específica' 14 | random_from_cat: 'Aleatoria desde Categoría' 15 | replace_x: 16 | post: 'Reemplazar X con el ID de la entrada' 17 | category: 'Reemplazar X con el ID de la categoría' 18 | -------------------------------------------------------------------------------- /config/locales/time.en_abbrev.yml: -------------------------------------------------------------------------------- 1 | en_abbrev: 2 | datetime: 3 | distance_in_words: 4 | x_seconds: '%{count}s' 5 | less_than_x_minutes: '<%{count}m' 6 | x_minutes: '%{count}m' 7 | about_x_hours: '~%{count}h' 8 | x_hours: '%{count}h' 9 | x_days: '%{count}d' 10 | x_weeks: '%{count}w' 11 | about_x_months: '~%{count}mo' 12 | x_months: '%{count}mo' 13 | x_years: '%{count}y' 14 | -------------------------------------------------------------------------------- /config/schedule.rb: -------------------------------------------------------------------------------- 1 | every 1.day, at: '02:00' do 2 | runner 'scripts/send_subscription_emails.rb' 3 | end 4 | 5 | every 6.hours do 6 | runner 'scripts/recalc_abilities.rb' 7 | end 8 | -------------------------------------------------------------------------------- /config/storage.sample.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join('tmp/storage') %> 4 | 5 | local: 6 | storage: Disk 7 | root: <%= Rails.root.join('storage') %> 8 | 9 | s3: 10 | service: S3 11 | access_key_id: "" 12 | secret_access_key: "" 13 | region: us-east-1 14 | bucket: "" -------------------------------------------------------------------------------- /db/migrate/20160424111446_add_user_levels_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddUserLevelsToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :is_moderator, :boolean 4 | add_column :users, :is_admin, :boolean 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160424113217_create_site_settings.rb: -------------------------------------------------------------------------------- 1 | class CreateSiteSettings < ActiveRecord::Migration 2 | def change 3 | create_table :site_settings do |t| 4 | t.string :name 5 | t.string :value 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20160424143518_create_questions.rb: -------------------------------------------------------------------------------- 1 | class CreateQuestions < ActiveRecord::Migration 2 | def change 3 | create_table :questions do |t| 4 | t.string :title 5 | t.string :body 6 | t.text :tags 7 | t.integer :score 8 | 9 | t.timestamps null: false 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20160424143813_add_user_to_questions.rb: -------------------------------------------------------------------------------- 1 | class AddUserToQuestions < ActiveRecord::Migration 2 | def change 3 | add_reference :questions, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160424162234_add_rep_and_name_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddRepAndNameToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :reputation, :integer 4 | add_column :users, :username, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160424172308_create_answers.rb: -------------------------------------------------------------------------------- 1 | class CreateAnswers < ActiveRecord::Migration 2 | def change 3 | create_table :answers do |t| 4 | t.string :body 5 | t.integer :score 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20160424172323_add_question_to_answer.rb: -------------------------------------------------------------------------------- 1 | class AddQuestionToAnswer < ActiveRecord::Migration 2 | def change 3 | add_reference :answers, :question, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160424172807_add_user_to_answers.rb: -------------------------------------------------------------------------------- 1 | class AddUserToAnswers < ActiveRecord::Migration 2 | def change 3 | add_reference :answers, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160424183802_create_votes.rb: -------------------------------------------------------------------------------- 1 | class CreateVotes < ActiveRecord::Migration 2 | def change 3 | create_table :votes do |t| 4 | t.integer :type 5 | 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20160424183824_add_user_and_post_to_votes.rb: -------------------------------------------------------------------------------- 1 | class AddUserAndPostToVotes < ActiveRecord::Migration 2 | def change 3 | add_reference :votes, :user, index: true, foreign_key: true 4 | add_reference :votes, :post, index: true, foreign_key: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160424191151_remove_post_from_votes.rb: -------------------------------------------------------------------------------- 1 | class RemovePostFromVotes < ActiveRecord::Migration 2 | def change 3 | remove_reference :votes, :post, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160424191405_add_polymorphic_post_to_votes.rb: -------------------------------------------------------------------------------- 1 | class AddPolymorphicPostToVotes < ActiveRecord::Migration 2 | def change 3 | add_reference :votes, :post, polymorphic: true, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160424193831_rename_votes_type_to_votes_vote_type.rb: -------------------------------------------------------------------------------- 1 | class RenameVotesTypeToVotesVoteType < ActiveRecord::Migration 2 | def change 3 | rename_column :votes, :type, :vote_type 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160428151443_add_user_to_privileges.rb: -------------------------------------------------------------------------------- 1 | class AddUserToPrivileges < ActiveRecord::Migration 2 | def change 3 | add_reference :privileges, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160428151900_add_name_to_privileges.rb: -------------------------------------------------------------------------------- 1 | class AddNameToPrivileges < ActiveRecord::Migration 2 | def change 3 | add_column :privileges, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160428152011_add_threshold_to_privileges.rb: -------------------------------------------------------------------------------- 1 | class AddThresholdToPrivileges < ActiveRecord::Migration 2 | def change 3 | add_column :privileges, :threshold, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160428202611_add_is_deleted_to_questions.rb: -------------------------------------------------------------------------------- 1 | class AddIsDeletedToQuestions < ActiveRecord::Migration 2 | def change 3 | add_column :questions, :is_deleted, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160429150239_add_is_deleted_to_answers.rb: -------------------------------------------------------------------------------- 1 | class AddIsDeletedToAnswers < ActiveRecord::Migration 2 | def change 3 | add_column :answers, :is_deleted, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160429160133_add_deleted_at_to_questions.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToQuestions < ActiveRecord::Migration 2 | def change 3 | add_column :questions, :deleted_at, :timestamp 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160429160144_add_deleted_at_to_answers.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedAtToAnswers < ActiveRecord::Migration 2 | def change 3 | add_column :answers, :deleted_at, :timestamp 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160430085505_create_notifications.rb: -------------------------------------------------------------------------------- 1 | class CreateNotifications < ActiveRecord::Migration 2 | def change 3 | create_table :notifications do |t| 4 | t.string :content 5 | t.string :link 6 | t.boolean :is_read 7 | 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20160430085520_add_user_to_notifications.rb: -------------------------------------------------------------------------------- 1 | class AddUserToNotifications < ActiveRecord::Migration 2 | def change 3 | add_reference :notifications, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160430092324_add_default_false_value_to_notifications.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultFalseValueToNotifications < ActiveRecord::Migration 2 | def change 3 | change_column :notifications, :is_read, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501095155_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration 2 | def change 3 | create_table :comments do |t| 4 | 5 | t.timestamps null: false 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20160501095354_add_post_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddPostToComments < ActiveRecord::Migration 2 | def change 3 | add_reference :comments, :post, polymorphic: true, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501101156_add_content_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddContentToComments < ActiveRecord::Migration 2 | def change 3 | add_column :comments, :content, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501103643_add_is_deleted_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddIsDeletedToComments < ActiveRecord::Migration 2 | def change 3 | add_column :comments, :is_deleted, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501105740_add_user_to_comments.rb: -------------------------------------------------------------------------------- 1 | class AddUserToComments < ActiveRecord::Migration 2 | def change 3 | add_reference :comments, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501150244_create_flags.rb: -------------------------------------------------------------------------------- 1 | class CreateFlags < ActiveRecord::Migration 2 | def change 3 | create_table :flags do |t| 4 | t.string :reason 5 | 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20160501150316_create_flag_statuses.rb: -------------------------------------------------------------------------------- 1 | class CreateFlagStatuses < ActiveRecord::Migration 2 | def change 3 | create_table :flag_statuses do |t| 4 | t.string :result 5 | t.string :message 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20160501150344_add_user_to_flags.rb: -------------------------------------------------------------------------------- 1 | class AddUserToFlags < ActiveRecord::Migration 2 | def change 3 | add_reference :flags, :user, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501150355_add_polymorphic_post_to_flags.rb: -------------------------------------------------------------------------------- 1 | class AddPolymorphicPostToFlags < ActiveRecord::Migration 2 | def change 3 | add_reference :flags, :post, polymorphic: true, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501150425_add_flag_to_flag_statuses.rb: -------------------------------------------------------------------------------- 1 | class AddFlagToFlagStatuses < ActiveRecord::Migration 2 | def change 3 | add_reference :flag_statuses, :flag, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160501203952_add_default_to_is_deleted.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultToIsDeleted < ActiveRecord::Migration 2 | def change 3 | change_column :answers, :is_deleted, :boolean, default: false 4 | change_column :comments, :is_deleted, :boolean, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160507112321_create_post_history_types.rb: -------------------------------------------------------------------------------- 1 | class CreatePostHistoryTypes < ActiveRecord::Migration 2 | def change 3 | create_table :post_history_types do |t| 4 | t.string :name 5 | t.string :description 6 | t.string :action_name 7 | 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20160507112635_create_post_histories.rb: -------------------------------------------------------------------------------- 1 | class CreatePostHistories < ActiveRecord::Migration 2 | def change 3 | create_table :post_histories do |t| 4 | t.references :post_history_type, index: true, foreign_key: true 5 | t.references :user, index: true, foreign_key: true 6 | t.string :title 7 | t.string :body 8 | t.string :tags 9 | 10 | t.timestamps null: false 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20160507112646_add_post_to_post_history.rb: -------------------------------------------------------------------------------- 1 | class AddPostToPostHistory < ActiveRecord::Migration 2 | def change 3 | add_reference :post_histories, :post, polymorphic: true, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160507135329_remove_post_fields_from_post_history.rb: -------------------------------------------------------------------------------- 1 | class RemovePostFieldsFromPostHistory < ActiveRecord::Migration 2 | def change 3 | remove_column :post_histories, :title, :string 4 | remove_column :post_histories, :body, :string 5 | remove_column :post_histories, :tags, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20160615175537_add_defaults_to_deleted.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultsToDeleted < ActiveRecord::Migration 2 | def change 3 | change_column :answers, :is_deleted, :boolean, default: false 4 | change_column :questions, :is_deleted, :boolean, default: false 5 | change_column :comments, :is_deleted, :boolean, default: false 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20160619161305_add_receiving_user_to_votes.rb: -------------------------------------------------------------------------------- 1 | class AddReceivingUserToVotes < ActiveRecord::Migration 2 | def change 3 | add_column :votes, :recv_user, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160619162714_create_suspicious_votes.rb: -------------------------------------------------------------------------------- 1 | class CreateSuspiciousVotes < ActiveRecord::Migration 2 | def change 3 | create_table :suspicious_votes do |t| 4 | t.integer :from_user 5 | t.integer :to_user 6 | t.boolean :was_investigated, default: false 7 | t.integer :investigated_by 8 | t.timestamp :investigated_at 9 | t.integer :suspicious_count 10 | t.integer :total_count 11 | 12 | t.timestamps null: false 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20160621093334_rename_user_attributes.rb: -------------------------------------------------------------------------------- 1 | class RenameUserAttributes < ActiveRecord::Migration 2 | def change 3 | rename_column :suspicious_votes, :from_user, :from_user_id 4 | rename_column :suspicious_votes, :to_user, :to_user_id 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160621102440_create_join_table_privilege_user.rb: -------------------------------------------------------------------------------- 1 | class CreateJoinTablePrivilegeUser < ActiveRecord::Migration 2 | def change 3 | create_join_table :privileges, :users do |t| 4 | t.index [:privilege_id, :user_id] 5 | t.index [:user_id, :privilege_id] 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20160621145835_add_close_fields_to_questions.rb: -------------------------------------------------------------------------------- 1 | class AddCloseFieldsToQuestions < ActiveRecord::Migration 2 | def change 3 | add_column :questions, :is_closed, :boolean 4 | add_column :questions, :closed_by, :integer 5 | add_column :questions, :closed_at, :timestamp 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20160621174102_rename_closed_by_to_closed_by_id.rb: -------------------------------------------------------------------------------- 1 | class RenameClosedByToClosedById < ActiveRecord::Migration 2 | def change 3 | rename_column :questions, :closed_by, :closed_by_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191109211244_change_site_settings_value_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeSiteSettingsValueType < ActiveRecord::Migration[5.0] 2 | def change 3 | change_column :site_settings, :value, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191110193734_remove_polymorphic_assoc_fields.rb: -------------------------------------------------------------------------------- 1 | class RemovePolymorphicAssocFields < ActiveRecord::Migration[5.0] 2 | def change 3 | drop_table :answers 4 | drop_table :questions 5 | remove_column :comments, :post_type 6 | remove_column :flags, :post_type 7 | remove_column :post_histories, :post_type 8 | remove_column :votes, :post_type 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20191110205100_rename_comments_is_deleted.rb: -------------------------------------------------------------------------------- 1 | class RenameCommentsIsDeleted < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :comments, :is_deleted, :deleted 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191110212601_add_post_defaults.rb: -------------------------------------------------------------------------------- 1 | class AddPostDefaults < ActiveRecord::Migration[5.0] 2 | def change 3 | change_column :posts, :deleted, :boolean, null: false, default: false 4 | change_column :posts, :closed, :boolean, null: false, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20191120165535_remove_action_name_from_post_history_types.rb: -------------------------------------------------------------------------------- 1 | class RemoveActionNameFromPostHistoryTypes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :post_history_types, :action_name 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191120170439_remove_user_id_from_privileges.rb: -------------------------------------------------------------------------------- 1 | class RemoveUserIdFromPrivileges < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :privileges, :user_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191122124913_change_recv_user_field_name_on_votes.rb: -------------------------------------------------------------------------------- 1 | class ChangeRecvUserFieldNameOnVotes < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :votes, :recv_user, :recv_user_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191124214828_add_value_type_to_site_settings.rb: -------------------------------------------------------------------------------- 1 | class AddValueTypeToSiteSettings < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :site_settings, :value_type, :string, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191125135227_add_description_to_site_settings.rb: -------------------------------------------------------------------------------- 1 | class AddDescriptionToSiteSettings < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :site_settings, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191125145708_add_name_indexes.rb: -------------------------------------------------------------------------------- 1 | class AddNameIndexes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :site_settings, :name 4 | add_index :privileges, :name 5 | add_index :post_types, :name 6 | add_index :post_history_types, :name 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20191127121809_add_body_markdown_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddBodyMarkdownToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :body_markdown, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191202195956_add_profile_attributes_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddProfileAttributesToUser < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :profile, :text 4 | add_column :users, :website, :text 5 | add_column :users, :twitter, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20191202215751_add_profile_markdown_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddProfileMarkdownToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :profile_markdown, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191204172132_create_tags.rb: -------------------------------------------------------------------------------- 1 | class CreateTags < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :tags do |t| 4 | t.string :name 5 | t.text :description 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20191204172148_create_post_tags_link_table.rb: -------------------------------------------------------------------------------- 1 | class CreatePostTagsLinkTable < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :posts_tags, id: false, primary_key: [:post_id, :tag_id] do |t| 4 | t.references :tag 5 | t.references :post 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20191204172543_rename_posts_tags.rb: -------------------------------------------------------------------------------- 1 | class RenamePostsTags < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :posts, :tags, :tags_cache 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191205115827_add_answer_count_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddAnswerCountToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :answer_count, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191205122016_add_default_to_answer_count.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultToAnswerCount < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :posts, :answer_count, :integer, default: 0, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191205122434_add_last_activity_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddLastActivityToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :last_activity, :datetime, default: -> { 'CURRENT_TIMESTAMP' }, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191205123038_rework_flag_system_tables.rb: -------------------------------------------------------------------------------- 1 | class ReworkFlagSystemTables < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :flags, :status, :string 4 | add_column :flags, :message, :text 5 | add_column :flags, :handled_by_id, :integer 6 | 7 | drop_table :flag_statuses 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20191205123408_add_handled_at_to_flags.rb: -------------------------------------------------------------------------------- 1 | class AddHandledAtToFlags < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :flags, :handled_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191205155835_add_state_fields_to_post_history.rb: -------------------------------------------------------------------------------- 1 | class AddStateFieldsToPostHistory < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :post_histories, :before_state, :text 4 | add_column :post_histories, :after_state, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20191205212204_add_attribution_fields_to_post.rb: -------------------------------------------------------------------------------- 1 | class AddAttributionFieldsToPost < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :att_source, :text 4 | add_column :posts, :att_license_name, :string 5 | add_column :posts, :att_license_link, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20191205225500_add_se_acct_id_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddSeAcctIdToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :se_acct_id, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191206213515_add_transferred_content_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddTransferredContentToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :transferred_content, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191207001359_add_search_fulltext_index_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddSearchFulltextIndexToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts, :body_markdown, type: :fulltext 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191207011614_add_is_meta_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddIsMetaToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :is_meta, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191208231830_add_doc_slug_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddDocSlugToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :doc_slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191215183139_add_last_activity_by_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddLastActivityByToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :posts, :last_activity_by, class_name: 'User' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191215211744_change_comments_content_field_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeCommentsContentFieldType < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :comments, :content, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191216161051_add_users_username_index.rb: -------------------------------------------------------------------------------- 1 | class AddUsersUsernameIndex < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :users, :username 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191217000359_add_comment_to_post_history.rb: -------------------------------------------------------------------------------- 1 | class AddCommentToPostHistory < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :post_histories, :comment, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191225135200_add_category_to_site_settings.rb: -------------------------------------------------------------------------------- 1 | class AddCategoryToSiteSettings < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :site_settings, :category, :string 4 | add_index :site_settings, :category 5 | end 6 | end -------------------------------------------------------------------------------- /db/migrate/20200109205444_change_settings_to_text_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeSettingsToTextType < ActiveRecord::Migration[5.2] 2 | def change 3 | SiteSetting.find_by(name: 'AskingGuidance').update(value_type: 'text') 4 | SiteSetting.find_by(name: 'AnsweringGuidance').update(value_type: 'text') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200115221655_create_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class CreateSubscriptions < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :subscriptions do |t| 4 | t.string :type, null: false 5 | t.string :qualifier 6 | t.references :user, foreign_key: true 7 | t.boolean :enabled, null: false 8 | t.integer :frequency, null: false 9 | t.datetime :last_sent_at, null: false 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20200116005738_add_name_to_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddNameToSubscriptions < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :subscriptions, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200116132702_add_default_to_subscriptions_enabled.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultToSubscriptionsEnabled < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :subscriptions, :enabled, :boolean, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200116132808_allow_null_subscriptions_last_sent.rb: -------------------------------------------------------------------------------- 1 | class AllowNullSubscriptionsLastSent < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :subscriptions, :last_sent_at, :datetime, null: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200122151548_add_category_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddCategoryToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :category, :string 4 | add_index :posts, :category 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200128123353_move_is_meta_to_category.rb: -------------------------------------------------------------------------------- 1 | class MoveIsMetaToCategory < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :posts, :category, :string, default: 'Main' 4 | Post.where(is_meta: true).update_all(category: 'Meta') 5 | Post.where(is_meta: [false, nil]).update_all(category: 'Main') 6 | remove_column :posts, :is_meta 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20200317173232_close_reasons.rb: -------------------------------------------------------------------------------- 1 | class CloseReasons < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :close_reasons do |t| 4 | t.string :name 5 | t.text :description 6 | t.boolean :active 7 | t.boolean :requires_other_post 8 | end 9 | add_reference :posts, :close_reasons, foreign_key: true, null: true 10 | add_reference :posts, :duplicate_post, foreign_key: {to_table: :posts}, null: true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20200318161617_add_comunity_scope_to_close_reasons.rb: -------------------------------------------------------------------------------- 1 | class AddComunityScopeToCloseReasons < ActiveRecord::Migration[5.2] 2 | def change 3 | change_table :close_reasons do |t| 4 | t.references :community 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200318164203_add_index_to_flags_status.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToFlagsStatus < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :flags, :status 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200321135935_create_tag_sets.rb: -------------------------------------------------------------------------------- 1 | class CreateTagSets < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :tag_sets do |t| 4 | t.string :name 5 | t.references :community, index: true, null: false 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20200323131708_add_indexes_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddIndexesToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts, :deleted 4 | add_index :posts, :parent_id 5 | add_index :posts, :user_id 6 | add_index :posts, :post_type_id 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20200411195247_create_categories.rb: -------------------------------------------------------------------------------- 1 | class CreateCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :categories do |t| 4 | t.string :name 5 | t.text :short_wiki 6 | t.references :community 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20200411195809_move_posts_to_category_reference.rb: -------------------------------------------------------------------------------- 1 | class MovePostsToCategoryReference < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :posts, :category, :old_category 4 | add_reference :posts, :category 5 | 6 | Community.all.each do |community| 7 | main_category = Category.unscoped.find_or_create_by(community: community, name: 'Main') 8 | meta_category = Category.unscoped.find_or_create_by(community: community, name: 'Meta') 9 | 10 | Post.unscoped.where(community: community, old_category: 'Main').update_all(category_id: main_category.id) 11 | Post.unscoped.where(community: community, old_category: 'Meta').update_all(category_id: meta_category.id) 12 | end 13 | 14 | remove_column :posts, :old_category 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20200411210022_create_categories_post_types.rb: -------------------------------------------------------------------------------- 1 | class CreateCategoriesPostTypes < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :categories_post_types, id: false, primary_key: [:category_id, :post_type_id] do |t| 4 | t.bigint :category_id, null: false 5 | t.bigint :post_type_id, null: false 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20200412121936_correct_close_reasons_reference_attribute_name.rb: -------------------------------------------------------------------------------- 1 | class CorrectCloseReasonsReferenceAttributeName < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :posts, :close_reasons_id, :close_reason_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200412122236_add_display_post_types_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddDisplayPostTypesToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :display_post_types, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200413144332_add_is_homepage_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddIsHomepageToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :is_homepage, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200413174714_add_tag_set_reference_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddTagSetReferenceToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :categories, :tag_set, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200420151217_add_trust_level_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddTrustLevelToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :trust_level, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200420151720_add_min_trust_level_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddMinTrustLevelToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :min_trust_level, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200422152359_add_button_text_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddButtonTextToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :button_text, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200428172814_create_licenses.rb: -------------------------------------------------------------------------------- 1 | class CreateLicenses < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :licenses do |t| 4 | t.string :name 5 | t.string :url 6 | t.boolean :default 7 | t.bigint :community_id, null: false 8 | 9 | t.timestamps 10 | end 11 | 12 | add_index :licenses, :community_id 13 | add_index :licenses, :name 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20200428173033_add_license_reference_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddLicenseReferenceToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :posts, :license, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200428181938_add_customization_fields_to_category.rb: -------------------------------------------------------------------------------- 1 | class AddCustomizationFieldsToCategory < ActiveRecord::Migration[5.2] 2 | def change 3 | change_table :categories do |t| 4 | t.string :color_code 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200430123008_add_posting_tips_overrides_to_category.rb: -------------------------------------------------------------------------------- 1 | class AddPostingTipsOverridesToCategory < ActiveRecord::Migration[5.2] 2 | def change 3 | change_table :categories do |t| 4 | t.text :asking_guidance_override 5 | t.text :answering_guidance_override 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20200430220415_create_error_logs.rb: -------------------------------------------------------------------------------- 1 | class CreateErrorLogs < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :error_logs do |t| 4 | t.references :community, foreign_key: true 5 | t.references :user, foreign_key: true 6 | t.string :klass 7 | t.text :message 8 | t.text :backtrace 9 | t.text :request_uri, null: false 10 | t.string :host, null: false 11 | 12 | t.timestamps 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20200430220944_add_uuid_to_error_logs.rb: -------------------------------------------------------------------------------- 1 | class AddUuidToErrorLogs < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :error_logs, :uuid, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200501215447_add_min_view_trust_level_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddMinViewTrustLevelToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :min_view_trust_level, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200502001225_add_license_reference_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddLicenseReferenceToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :categories, :license, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200502152723_add_enabled_to_licenses.rb: -------------------------------------------------------------------------------- 1 | class AddEnabledToLicenses < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :licenses, :enabled, :boolean, default: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200503110754_add_qr_login_attributes_to_user.rb: -------------------------------------------------------------------------------- 1 | class AddQrLoginAttributesToUser < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :login_token, :string, unique: true 4 | add_column :users, :login_token_expires_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200504213143_add_two_factor_token_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddTwoFactorTokenToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :two_factor_token, :string 4 | add_column :users, :enabled_2fa, :boolean, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200507235849_add_user_agent_to_error_logs.rb: -------------------------------------------------------------------------------- 1 | class AddUserAgentToErrorLogs < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :error_logs, :user_agent, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200508112958_add_sequence_to_categories.rb: -------------------------------------------------------------------------------- 1 | class AddSequenceToCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :sequence, :integer 4 | add_index :categories, :sequence 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200508115752_add_category_tag_join_tables.rb: -------------------------------------------------------------------------------- 1 | class AddCategoryTagJoinTables < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :categories_required_tags, id: false, primary_key: [:category_id, :tag_id] do |t| 4 | t.bigint :category_id 5 | t.bigint :tag_id 6 | end 7 | 8 | create_table :categories_topic_tags, id: false, primary_key: [:category_id, :tag_id] do |t| 9 | t.bigint :category_id 10 | t.bigint :tag_id 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20200515212247_add_post_indexes.rb: -------------------------------------------------------------------------------- 1 | class AddPostIndexes < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :posts, :att_source, :string 4 | add_index :posts, :att_source 5 | add_index :posts, :tags_cache 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200516162625_update_answer_count_column.rb: -------------------------------------------------------------------------------- 1 | class UpdateAnswerCountColumn < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :posts, :answer_count, :integer, null: false, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200517105207_add_confirmable_to_devise.rb: -------------------------------------------------------------------------------- 1 | class AddConfirmableToDevise < ActiveRecord::Migration[5.2] 2 | def up 3 | add_column :users, :confirmation_token, :string 4 | add_column :users, :confirmed_at, :datetime 5 | add_column :users, :confirmation_sent_at, :datetime 6 | add_column :users, :unconfirmed_email, :string 7 | add_index :users, :confirmation_token, unique: true 8 | 9 | User.update_all confirmed_at: DateTime.now 10 | end 11 | 12 | def down 13 | remove_columns :users, :confirmation_token, :confirmed_at, :confirmation_sent_at 14 | remove_columns :users, :unconfirmed_email 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20200528145307_add_two_factor_method_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddTwoFactorMethodToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :two_factor_method, :string 4 | User.where(enabled_2fa: true).update_all(two_factor_method: 'app') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200601113238_add_index_to_last_activity.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToLastActivity < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts, :last_activity 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200610150214_add_help_attributes_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddHelpAttributesToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :help_category, :string 4 | add_column :posts, :help_ordering, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200610152505_allow_post_community_id_null.rb: -------------------------------------------------------------------------------- 1 | class AllowPostCommunityIdNull < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column_null :posts, :community_id, true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200610152647_allow_post_history_community_id_null.rb: -------------------------------------------------------------------------------- 1 | class AllowPostHistoryCommunityIdNull < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column_null :post_histories, :community_id, true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200612154828_add_unique_index_to_posts_tags.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToPostsTags < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts_tags, [:post_id, :tag_id], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200616224440_change_to_wilson_scores.rb: -------------------------------------------------------------------------------- 1 | class ChangeToWilsonScores < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :upvote_count, :integer, null: false, default: 0 4 | add_column :posts, :downvote_count, :integer, null: false, default: 0 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200617140007_change_post_score_column_type.rb: -------------------------------------------------------------------------------- 1 | class ChangePostScoreColumnType < ActiveRecord::Migration[5.2] 2 | def change 3 | change_column :posts, :score, :decimal, precision: 10, scale: 8 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200618094826_add_suspensions_and_warnings.rb: -------------------------------------------------------------------------------- 1 | class AddSuspensionsAndWarnings < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :warnings do |t| 4 | t.references :community_user, foreign_key: true 5 | 6 | t.text :body, null: true 7 | t.boolean :is_suspension 8 | t.datetime :suspension_end 9 | t.boolean :active 10 | 11 | t.references :author, foreign_key: {to_table: :users}, null: true 12 | 13 | t.timestamps 14 | end 15 | 16 | add_column :community_users, :is_suspended, :boolean 17 | add_column :community_users, :suspension_end, :datetime 18 | add_column :community_users, :suspension_public_comment, :string 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20200618124645_add_warning_templates.rb: -------------------------------------------------------------------------------- 1 | class AddWarningTemplates < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :warning_templates do |t| 4 | t.references :community, foreign_key: true 5 | 6 | t.string :name 7 | t.text :body 8 | t.boolean :active 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20200625115618_add_mod_tags_join_table.rb: -------------------------------------------------------------------------------- 1 | class AddModTagsJoinTable < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :categories_moderator_tags, id: false, primary_key: [:category_id, :tag_id] do |t| 4 | t.bigint :category_id 5 | t.bigint :tag_id 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20200629131408_update_tag_model.rb: -------------------------------------------------------------------------------- 1 | class UpdateTagModel < ActiveRecord::Migration[5.2] 2 | def change 3 | remove_column :tags, :description 4 | add_column :tags, :wiki_markdown, :text 5 | add_column :tags, :excerpt_markdown, :text 6 | add_column :tags, :wiki, :text 7 | add_column :tags, :excerpt, :text 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20200630001048_remove_excerpt_markdown.rb: -------------------------------------------------------------------------------- 1 | class RemoveExcerptMarkdown < ActiveRecord::Migration[5.2] 2 | def change 3 | remove_column :tags, :excerpt_markdown 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200630105117_allow_tag_parents.rb: -------------------------------------------------------------------------------- 1 | class AllowTagParents < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :tags, :parent, foreign_key: { to_table: :tags } 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200701132522_add_index_to_post_score.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToPostScore < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts, :score 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200701132654_add_indexes_to_vote_counts.rb: -------------------------------------------------------------------------------- 1 | class AddIndexesToVoteCounts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :posts, :upvote_count 4 | add_index :posts, :downvote_count 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200709204628_create_audit_logs.rb: -------------------------------------------------------------------------------- 1 | class CreateAuditLogs < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :audit_logs do |t| 4 | t.string :log_type 5 | t.string :event_type 6 | t.references :related, polymorphic: true 7 | t.references :user, foreign_key: true 8 | t.text :comment 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20200709204728_add_audit_indexes.rb: -------------------------------------------------------------------------------- 1 | class AddAuditIndexes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_index :audit_logs, :log_type 4 | add_index :audit_logs, :event_type 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200711121645_add_community_to_audit_logs.rb: -------------------------------------------------------------------------------- 1 | class AddCommunityToAuditLogs < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :audit_logs, :community, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200716081538_create_blocked_items.rb: -------------------------------------------------------------------------------- 1 | class CreateBlockedItems < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :blocked_items do |t| 4 | t.string :type 5 | t.text :value 6 | t.datetime :expires 7 | t.boolean :automatic 8 | t.string :reason, null: true 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20200716191141_add_comments_disabled_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddCommentsDisabledToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :comments_disabled, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200718163608_rename_type_column_of_blocked_items.rb: -------------------------------------------------------------------------------- 1 | class RenameTypeColumnOfBlockedItems < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :blocked_items, :type, :item_type 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200721185048_add_title_and_tags_to_post_history.rb: -------------------------------------------------------------------------------- 1 | class AddTitleAndTagsToPostHistory < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :post_histories, :before_title, :string 4 | add_column :post_histories, :after_title, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200721185230_create_post_history_tags.rb: -------------------------------------------------------------------------------- 1 | class CreatePostHistoryTags < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :post_history_tags do |t| 4 | t.references :post_history, foreign_key: true 5 | t.references :tag, foreign_key: true 6 | t.string :relationship 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20200727183756_create_pinned_links.rb: -------------------------------------------------------------------------------- 1 | class CreatePinnedLinks < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :pinned_links do |t| 4 | t.references :community, null: true, foreign_key: true 5 | t.string :label, null: true 6 | t.string :link, null: true 7 | t.references :post, null: true, foreign_key: true 8 | t.boolean :active 9 | t.datetime :shown_after, null: true 10 | t.datetime :shown_before, null: true 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20200728093322_add_eligible_for_hot_post_to_category.rb: -------------------------------------------------------------------------------- 1 | class AddEligibleForHotPostToCategory < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :categories, :use_for_hot_posts, :boolean, default: true 4 | add_column :categories, :use_for_advertisement, :boolean, default: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200806103121_add_staff_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddStaffToUsers < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :users, :staff, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200810153141_create_trust_levels.rb: -------------------------------------------------------------------------------- 1 | class CreateTrustLevels < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :trust_levels do |t| 4 | t.references :community, foreign_key: true 5 | t.string :name 6 | t.text :description 7 | t.string :internal_id 8 | t.string :icon 9 | t.decimal :post_score_threshold, null: true, precision: 10, scale: 8 10 | t.decimal :edit_score_threshold, null: true, precision: 10, scale: 8 11 | t.decimal :flag_score_threshold, null: true, precision: 10, scale: 8 12 | t.timestamps 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20200810153831_create_user_privileges.rb: -------------------------------------------------------------------------------- 1 | class CreateUserPrivileges < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :user_privileges do |t| 4 | t.references :community_user, foreign_key: true 5 | t.references :trust_level, foreign_key: true 6 | t.boolean :is_suspended, default: false 7 | t.datetime :suspension_end, null: true 8 | t.text :suspension_message, null: true 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20200813125349_rename_ability_tables.rb: -------------------------------------------------------------------------------- 1 | class RenameAbilityTables < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_table :trust_levels, :abilities 4 | rename_table :user_privileges, :user_abilities 5 | rename_column :user_abilities, :trust_level_id, :ability_id 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200813132829_enforce_concurrence_of_is_moderator_and_mod_ability.rb: -------------------------------------------------------------------------------- 1 | class EnforceConcurrenceOfIsModeratorAndModAbility < ActiveRecord::Migration[5.2] 2 | def up 3 | CommunityUser.unscoped.where(is_moderator: true).all.map do |cu| 4 | RequestContext.community = cu.community 5 | cu.grant_privilege 'mod' 6 | end 7 | end 8 | 9 | def down 10 | # Nothing to do, because the up only duplicates content, 11 | # which cannot be easily reversed without likely quite 12 | # complex algorithmis. This is unneccessary, because the duplicate 13 | # content isn't harmful in any way. 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20200813141412_have_two_descriptions_on_abilities.rb: -------------------------------------------------------------------------------- 1 | class HaveTwoDescriptionsOnAbilities < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :abilities, :summary, :text 4 | 5 | Ability.unscoped.all.each do |a| 6 | a.update summary: a.description 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20200814203051_create_post_flag_types.rb: -------------------------------------------------------------------------------- 1 | class CreatePostFlagTypes < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :post_flag_types do |t| 4 | t.references :community 5 | t.string :name 6 | t.text :description 7 | t.boolean :confidential 8 | t.boolean :active 9 | t.references :post_type, null: true 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20200815103111_add_post_flag_type_id_to_flags.rb: -------------------------------------------------------------------------------- 1 | class AddPostFlagTypeIdToFlags < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :flags, :post_flag_type, null: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200815191909_add_locked_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddLockedToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :locked, :boolean, null: false, default: false 4 | add_reference :posts, :locked_by, foreign_key: { to_table: :users }, null: true 5 | add_column :posts, :locked_at, :datetime, null: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200815193704_add_locked_until_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddLockedUntilToPosts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :locked_until, :datetime, null: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200829235149_add_edit_fields_to_post.rb: -------------------------------------------------------------------------------- 1 | class AddEditFieldsToPost < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :posts, :last_edited_at, :datetime 4 | add_column :posts, :last_edited_by_id, :bigint 5 | add_index :posts, :last_edited_by_id 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20200910103140_add_before_columns_to_suggested_edit.rb: -------------------------------------------------------------------------------- 1 | class AddBeforeColumnsToSuggestedEdit < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :suggested_edits, :before_title, :string 4 | add_column :suggested_edits, :before_body, :text 5 | add_column :suggested_edits, :before_body_markdown, :text 6 | add_column :suggested_edits, :before_tags_cache, :string 7 | 8 | create_table :suggested_edits_before_tags, id: false, primary_key: [:suggested_edit_id, :tag_id] do |t| 9 | t.bigint :suggested_edit_id, null: false 10 | t.bigint :tag_id, null: false 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20201001085031_add_read_to_mod_warning.rb: -------------------------------------------------------------------------------- 1 | class AddReadToModWarning < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :warnings, :read, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20201118222120_create_ability_queues.rb: -------------------------------------------------------------------------------- 1 | class CreateAbilityQueues < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :ability_queues do |t| 4 | t.references :community_user 5 | t.text :comment, null: true 6 | t.boolean :completed 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20201123132854_add_lockable_omniauthable.rb: -------------------------------------------------------------------------------- 1 | class AddLockableOmniauthable < ActiveRecord::Migration[5.2] 2 | def change 3 | change_table :users do |t| 4 | t.integer :failed_attempts, default: 0, null: false 5 | t.string :unlock_token 6 | t.datetime :locked_at 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20201212235514_move_trust_level_to_community_user.rb: -------------------------------------------------------------------------------- 1 | class MoveTrustLevelToCommunityUser < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :community_users, :trust_level, :integer 4 | remove_column :users, :trust_level 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20201216225353_add_is_freely_editable_to_post_types.rb: -------------------------------------------------------------------------------- 1 | class AddIsFreelyEditableToPostTypes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :post_types, :is_freely_editable, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/scripts/create_tags_path_view.rb: -------------------------------------------------------------------------------- 1 | ActiveRecord::Base.connection.execute File.read(Rails.root.join('db/scripts/create_tags_path_view.sql')) -------------------------------------------------------------------------------- /db/scripts/tag_children.sql: -------------------------------------------------------------------------------- 1 | WITH RECURSIVE CTE (id, group_id) AS ( 2 | SELECT id, parent_id 3 | FROM tags 4 | WHERE parent_id = $ParentId 5 | UNION ALL 6 | SELECT t.id, t.parent_id 7 | FROM tags t 8 | INNER JOIN CTE ON t.parent_id = CTE.id 9 | ) 10 | SELECT * FROM CTE; -------------------------------------------------------------------------------- /db/seeds/abilities/edit_tags.html: -------------------------------------------------------------------------------- 1 |

What does this ability allow me to do?

2 |

This ability allows you to unilaterally edit tag metadata, including the usage guidance and the detailed tag wiki.

3 | 4 |

The usage guidance for a tag should detail how the tag should be used, such as what type of question or article should use this tag. The detailed tag wiki can be used to include more details about either the tag usage or the subject of the tag.

5 | 6 |

How do I earn this ability?

7 |

To earn this ability, you need to have roughly a 97.5% approval rate for suggested edits to either the detailed tag wiki or the usage guidance for tags, with a hard minimum of 76 approved suggested edits (these numbers may vary from site to site).

-------------------------------------------------------------------------------- /db/seeds/abilities/everyone.html: -------------------------------------------------------------------------------- 1 |

What does this ability allow me to do?

2 | 3 |

This ability allows you to posts 3 top-level posts (questions and articles) a day, and to post 20 answers a day.

4 | 5 |

This ability also allows you to raise 15 flags on posts a day.

6 | 7 |

How do I earn this ability?

8 | 9 |

This ability is automatically granted to you when you create an account.

-------------------------------------------------------------------------------- /db/seeds/abilities/mod.html: -------------------------------------------------------------------------------- 1 |

What does this ability allow me to do?

2 | 3 |

This ability allows you to see and handle all types of flags; permanently lock posts; unilaterally close, reopen, delete, or undelete posts; suspend or unsuspend users, as well as further moderator abilities. Moderators also have access to special moderator-specific help pages.

4 | 5 |

Moderators are signified with a special symbol next to their usernames.

6 | 7 |

How do I earn this ability?

8 | 9 |

Moderators are elected by the community, or appointed by the Codidact Team.

-------------------------------------------------------------------------------- /db/seeds/abilities/unrestricted.html: -------------------------------------------------------------------------------- 1 |

What does this ability allow me to do?

2 |

This ability allows you to post questions, articles, and answers without limit, as well as being able to vote and leave comments on any post. You can see guidance on asking questions and how to vote in the Help Center.

3 | 4 |

How do I earn this ability?

5 |

To earn this ability, you need to have roughly 75% of your posts be positively received, with a minimum of 5 positively-recieved posts (these numbers may vary from site to site).

6 | -------------------------------------------------------------------------------- /db/seeds/licenses.yml: -------------------------------------------------------------------------------- 1 | - name: CC BY-SA 4.0 2 | url: https://creativecommons.org/licenses/by-sa/4.0 3 | default: true 4 | enabled: true 5 | 6 | - name: CC BY 4.0 7 | url: https://creativecommons.org/licenses/by/4.0 8 | default: false 9 | enabled: true 10 | 11 | - name: CC BY-NC 4.0 12 | url: https://creativecommons.org/licenses/by-nc/4.0 13 | default: false 14 | enabled: true 15 | 16 | - name: CC BY-NC-SA 4.0 17 | url: https://creativecommons.org/licenses/by-nc-sa/4.0 18 | default: false 19 | enabled: true 20 | 21 | - name: CC0 22 | url: https://creativecommons.org/publicdomain/zero/1.0/ 23 | default: false 24 | enabled: true 25 | -------------------------------------------------------------------------------- /db/seeds/post_history_types.yml: -------------------------------------------------------------------------------- 1 | - name: post_edited 2 | - name: post_deleted 3 | - name: post_undeleted 4 | - name: question_closed 5 | - name: question_reopened 6 | - name: initial_revision 7 | - name: attribution_notice_added 8 | - name: attribution_notice_removed 9 | - name: attribution_notice_changed 10 | - name: imported_from_external_source -------------------------------------------------------------------------------- /db/seeds/post_types.yml: -------------------------------------------------------------------------------- 1 | - name: Question 2 | - name: Answer 3 | - name: PolicyDoc 4 | - name: HelpDoc 5 | - name: Article -------------------------------------------------------------------------------- /db/seeds/site_settings/asking_guidance.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /db/seeds/tag_sets.yml: -------------------------------------------------------------------------------- 1 | - name: Main 2 | - name: Meta -------------------------------------------------------------------------------- /db/seeds/users.yml: -------------------------------------------------------------------------------- 1 | - id: -1 2 | username: System 3 | password: saK4CZR6b5gVZRvwMuzHDDFR518kktUYszBMZh47zqNkMJtuHnYDN5pcXwtbGUZlFIiwBFNIsbKYDVZ07kydul33sJvKVHKECZXhVZbNrjkI2YzDRTwpV1lBp1ZWAARP 4 | encrypted_password: abcdefghijklmnopqrstuvwxyz 5 | email: system@localhost 6 | profile_markdown: > 7 | This is an anonymous user account for system operations. It owns automatically-run operations and 8 | content from deleted users, among other things. 9 | profile: > 10 |

This is an anonymous user account for system operations. It owns automatically-run operations and 11 | content from deleted users, among other things.

12 | is_global_moderator: true 13 | is_global_admin: true 14 | -------------------------------------------------------------------------------- /db/seeds/warning_templates.yml: -------------------------------------------------------------------------------- 1 | - name: Spam 2 | body: $FILE warning_templates/spam.md 3 | active: true 4 | 5 | - name: Rudeness 6 | body: $FILE warning_templates/rudeness.md 7 | active: true 8 | 9 | - name: Many off-topic posts 10 | body: $FILE warning_templates/off-topic.md 11 | active: true -------------------------------------------------------------------------------- /db/seeds/warning_templates/spam.md: -------------------------------------------------------------------------------- 1 | We've noticed that in addition to your contributions to $SiteName, you've also been using this account to promote a product, service, or similar. 2 | 3 | This is a gentle reminder that using an account for promotional purposes is against the rules of this site. 4 | 5 | Please take a moment to review the guidelines for promotional content here on $SiteName, which can be found in the [help center](/policy/spam). 6 | 7 | While we appreciate your continued contributions to $SiteName, we do ask that you stay within the boundaries of the rules about promotional content. -------------------------------------------------------------------------------- /docker/Dockerfile.db: -------------------------------------------------------------------------------- 1 | FROM mysql 2 | 3 | # docker build -t qpixel_db -f docker/Dockerfile.db . 4 | 5 | # These commands will be run on init of the container 6 | COPY docker/mysql-init.sql /docker-entrypoint-initdb.d/mysql-init.sql 7 | -------------------------------------------------------------------------------- /docker/compose-env: -------------------------------------------------------------------------------- 1 | LOCAL_DEV_PORT=3000 2 | COMMUNITY_NAME=Dev Community 3 | RAILS_ENV=development 4 | CONFIRMABLE_ALLOWED_ACCESS_DAYS=2 5 | ENV_FILE_LOCATION=./docker/env 6 | -------------------------------------------------------------------------------- /docker/create_admin_and_community.rb: -------------------------------------------------------------------------------- 1 | # 1. Create the community 2 | community_name = ENV['COMMUNITY_NAME'] || 'Dinosaur Community' 3 | Community.create(name: community_name, host: "localhost:#{ENV['LOCAL_DEV_PORT']}") 4 | 5 | # 2. Create the admin user, ensure doesn't require confirmation 6 | username = ENV['COMMUNITY_ADMIN_USERNAME'] || 'admin' 7 | password = ENV['COMMUNITY_ADMIN_PASSWORD'] || 'password' 8 | email = ENV['COMMUNITY_ADMIN_EMAIL'] || 'codadict@noreply.com' 9 | 10 | User.create(username: username, password: password, email: email, is_global_admin: true, is_global_moderator: true, 11 | staff: true) 12 | # You'll need to manually set confirmation for this user 13 | # $ docker exec qpixel_uwsgi_1 rails runner "User.second.update(confirmed_at: DateTime.now)" 14 | -------------------------------------------------------------------------------- /docker/dummy.env: -------------------------------------------------------------------------------- 1 | MYSQL_ROOT_PASSWORD=qpixel 2 | MYSQL_DATABASE=qpixel 3 | MYSQL_USER=qpixel 4 | MYSQL_PASSWORD=qpixel 5 | COMMUNITY_ADMIN_USERNAME=admin 6 | COMMUNITY_ADMIN_PASSWORD=password 7 | COMMUNITY_ADMIN_EMAIL=admin@noreply.com 8 | -------------------------------------------------------------------------------- /docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Give database chance to finish creation 4 | sleep 15 5 | 6 | # If not created yet 7 | if [ ! -f "/db-created" ]; then 8 | rails db:create 9 | rails db:schema:load 10 | rails r db/scripts/create_tags_path_view.rb 11 | rails db:migrate 12 | rails db:migrate RAILS_ENV=development 13 | rails db:seed 14 | rails r docker/create_admin_and_community.rb 15 | touch /db-created 16 | fi 17 | 18 | # If this isn't done again, there is a 500 error on the first page about posts 19 | rails db:seed 20 | 21 | # defaults to port 3000 22 | rails server -b 0.0.0.0 23 | -------------------------------------------------------------------------------- /docker/img/categories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/categories.png -------------------------------------------------------------------------------- /docker/img/create-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/create-post.png -------------------------------------------------------------------------------- /docker/img/interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/interface.png -------------------------------------------------------------------------------- /docker/img/logged-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/logged-in.png -------------------------------------------------------------------------------- /docker/img/post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/post.png -------------------------------------------------------------------------------- /docker/img/tagset-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/tagset-selected.png -------------------------------------------------------------------------------- /docker/img/tagset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/docker/img/tagset.png -------------------------------------------------------------------------------- /docker/local-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cp ./docker/dummy.env ./docker/env 4 | cp ./docker/compose-env .env 5 | cp config/database.docker.yml config/database.yml 6 | -------------------------------------------------------------------------------- /docker/mysql-init.sql: -------------------------------------------------------------------------------- 1 | 2 | /* database qpixel and user are already created * 3 | if you change your environment file, you need to update database names here */ 4 | CREATE DATABASE qpixel_dev; 5 | CREATE DATABASE qpixel_test; 6 | GRANT ALL ON qpixel_dev.* TO qpixel; 7 | GRANT ALL ON qpixel_test.* TO qpixel; 8 | GRANT ALL ON qpixel.* TO qpixel; 9 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/lib/tasks/.keep -------------------------------------------------------------------------------- /public/assets/ability-help/close-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/ability-help/close-dialog.png -------------------------------------------------------------------------------- /public/assets/ability-help/edit-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/ability-help/edit-link.png -------------------------------------------------------------------------------- /public/assets/ability-help/flag-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/ability-help/flag-dialog.png -------------------------------------------------------------------------------- /public/assets/ability-help/flag-inline-handling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/ability-help/flag-inline-handling.png -------------------------------------------------------------------------------- /public/assets/ability-help/voting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/ability-help/voting.png -------------------------------------------------------------------------------- /public/assets/codidact-org.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/codidact-org.png -------------------------------------------------------------------------------- /public/assets/codidactyl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/codidactyl.png -------------------------------------------------------------------------------- /public/assets/down-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/down-clear.png -------------------------------------------------------------------------------- /public/assets/down-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/down-fill.png -------------------------------------------------------------------------------- /public/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/favicon.png -------------------------------------------------------------------------------- /public/assets/logo-writing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/logo-writing.png -------------------------------------------------------------------------------- /public/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/logo.png -------------------------------------------------------------------------------- /public/assets/privacy-policy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/privacy-policy.pdf -------------------------------------------------------------------------------- /public/assets/scoring_3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/scoring_3d.png -------------------------------------------------------------------------------- /public/assets/scoring_distribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/scoring_distribution.png -------------------------------------------------------------------------------- /public/assets/scoring_formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/scoring_formula.png -------------------------------------------------------------------------------- /public/assets/scoring_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/scoring_table.png -------------------------------------------------------------------------------- /public/assets/tour-clippy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/tour-clippy.png -------------------------------------------------------------------------------- /public/assets/tour-evil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/tour-evil.png -------------------------------------------------------------------------------- /public/assets/up-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/up-clear.png -------------------------------------------------------------------------------- /public/assets/up-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/assets/up-fill.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /scripts/clear_cache.rb: -------------------------------------------------------------------------------- 1 | Rails.cache.clear -------------------------------------------------------------------------------- /scripts/create_initial_tags.rb: -------------------------------------------------------------------------------- 1 | @options = {} 2 | OptionParser.new do |opts| 3 | opts.on('-c COMMUNITY_ID', '--community=COMMUNITY_ID', Integer) 4 | opts.on('-t TAG_SET_ID', '--tag-set=TAG_SET_ID', Integer) do |t| 5 | @options[:tag_set] = t 6 | end 7 | end.parse!(into: @options) 8 | 9 | tags = ARGV 10 | 11 | created = Tag.create(tags.map { |t| { name: t, community_id: @options[:community], tag_set_id: @options[:tag_set] } }) 12 | puts "Created #{created.size} tags." -------------------------------------------------------------------------------- /scripts/recalc_abilities.rb: -------------------------------------------------------------------------------- 1 | puts "Recalculating the Abilities (Scheduled)" 2 | puts 3 | 4 | resolved = [] 5 | 6 | AbilityQueue.pending.map do |q| 7 | cu = q.community_user 8 | puts "Scope: CommunityUser.Id=#{cu.id}" 9 | RequestContext.community = cu.community 10 | cu.recalc_privileges 11 | 12 | # Grant mod ability if mod status is given 13 | if (cu.is_moderator || cu.is_admin || u.is_global_moderator || u.is_global_admin) && !cu.privilege?('mod') 14 | cu.grant_privilege('mod') 15 | end 16 | 17 | resolved << q.id 18 | rescue 19 | puts " Failed." 20 | end 21 | 22 | # Mark resolved queue tasks as completed 23 | AbilityQueue.where(id: resolved).update(completed: true) 24 | 25 | puts "---" 26 | puts "Recalculating completed" -------------------------------------------------------------------------------- /scripts/recalc_abilities_upon_first_migration.rb: -------------------------------------------------------------------------------- 1 | puts "Recalculating all the Abilities" 2 | puts 3 | 4 | User.unscoped.all.map do |u| 5 | puts "Scope: User.Id=#{u.id}" 6 | CommunityUser.unscoped.where(user: u).all.map do |cu| 7 | puts " Attempt CommunityUser.Id=#{cu.id}" 8 | RequestContext.community = cu.community 9 | cu.recalc_privileges 10 | 11 | if (cu.is_moderator || cu.is_admin || u.is_global_moderator || u.is_global_admin) && !cu.privilege?('mod') 12 | cu.grant_privilege('mod') 13 | end 14 | rescue 15 | puts " !!! Error recalcing for CommunityUser.Id=#{cu.id}" 16 | end 17 | puts "End" 18 | puts 19 | end 20 | 21 | puts "---" 22 | puts "Recalculating completed" 23 | -------------------------------------------------------------------------------- /scripts/remove_exact_duplicates.sql: -------------------------------------------------------------------------------- 1 | UPDATE posts 2 | SET deleted = TRUE, 3 | deleted_at = CURRENT_TIMESTAMP, 4 | deleted_by_id = -1 5 | WHERE id IN ( 6 | SELECT * FROM ( 7 | SELECT IF(b.answer_count = 0, b.id, a.id) AS id 8 | FROM posts a 9 | JOIN posts b ON a.id < b.id AND a.user_id = b.user_id 10 | AND a.title IS NOT NULL AND b.title IS NOT NULL 11 | AND a.title = b.title 12 | AND a.deleted_at IS NULL AND b.deleted_at IS NULL 13 | AND a.community_id = b.community_id 14 | LEFT JOIN posts c ON c.parent_id = b.id 15 | WHERE c.id IS NULL 16 | ) q 17 | ); -------------------------------------------------------------------------------- /scripts/send_subscription_emails.rb: -------------------------------------------------------------------------------- 1 | # SQL for selecting subscriptions due for sending. 2 | # DO NOT USE USER INPUT IN THIS CLAUSE, IT GETS PASSED DIRECTLY TO Arel.sql 3 | select_clause = 'last_sent_at IS NULL OR DATE_ADD(last_sent_at, INTERVAL frequency DAY) <= CURRENT_TIMESTAMP' 4 | 5 | Subscription.unscoped.where(Arel.sql(select_clause)).includes(:community).each do |sub| 6 | SubscriptionMailer.with(subscription: sub).subscription.deliver_now 7 | end -------------------------------------------------------------------------------- /scripts/wipe_everything.rb: -------------------------------------------------------------------------------- 1 | unless Rails.env.development? 2 | puts "You're on production. Don't be dumb." 3 | exit 255 4 | end 5 | 6 | def exec(sql) 7 | ActiveRecord::Base.connection.execute sql 8 | end 9 | 10 | conn = ActiveRecord::Base.connection 11 | leave_tables = ['ar_internal_metadata', 'schema_migrations'] 12 | (conn.tables - leave_tables).each do |t| 13 | exec "DELETE FROM `#{t}`" 14 | exec "ALTER TABLE `#{t}` AUTO_INCREMENT=1" 15 | end 16 | 17 | Rails.cache.clear 18 | 19 | `bundle exec rails db:seed` -------------------------------------------------------------------------------- /test/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - '../.rubocop.yml' 3 | 4 | Layout/LineLength: 5 | Max: 150 6 | 7 | Metrics/ClassLength: 8 | Enabled: false -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/controllers/.keep -------------------------------------------------------------------------------- /test/controllers/articles_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ArticlesControllerTest < ActionController::TestCase 4 | include Devise::Test::ControllerHelpers 5 | end 6 | -------------------------------------------------------------------------------- /test/controllers/birthday_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class BirthdayControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/pinned_links_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PinnedLinksControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/post_history_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PostHistoryControllerTest < ActionController::TestCase 4 | include Devise::Test::ControllerHelpers 5 | 6 | test 'should get post history page' do 7 | get :post, params: { id: posts(:question_one).id } 8 | assert_response 200 9 | assert_not_nil assigns(:history) 10 | assert_not_nil assigns(:post) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/controllers/questions_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class QuestionsControllerTest < ActionController::TestCase 4 | include Devise::Test::ControllerHelpers 5 | include ApplicationTestHelper 6 | end 7 | -------------------------------------------------------------------------------- /test/controllers/tour_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TourControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/two_factor_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TwoFactorControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/fixtures/.keep -------------------------------------------------------------------------------- /test/fixtures/ability_queues.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/audit_logs.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | admin_log: 4 | community: sample 5 | log_type: admin_audit 6 | event_type: setting_update 7 | related_type: SiteSetting 8 | related: one 9 | user: admin 10 | comment: some words 11 | -------------------------------------------------------------------------------- /test/fixtures/blocked_items.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/close_reasons.yml: -------------------------------------------------------------------------------- 1 | duplicate: 2 | name: duplicate 3 | description: duplicate 4 | active: true 5 | requires_other_post: true 6 | community: sample 7 | 8 | not_good: 9 | name: not good 10 | description: not good 11 | active: true 12 | requires_other_post: false 13 | community: sample -------------------------------------------------------------------------------- /test/fixtures/comments.yml: -------------------------------------------------------------------------------- 1 | one: 2 | user: standard_user 3 | post: question_one 4 | content: ABCDEF GHIJKL MNOPQR 5 | community: sample 6 | 7 | two: 8 | user: standard_user 9 | post: question_two 10 | content: ABCDEF GHIJKL MNOPQR 11 | community: sample 12 | 13 | on_answer: 14 | user: standard_user 15 | post: answer_one 16 | content: ABCDEF GHIJKL MNOPQR 17 | community: sample 18 | 19 | deleted: 20 | user: standard_user 21 | post: question_one 22 | content: ABCDEF GHIJKL MNOPQR 23 | deleted: true 24 | community: sample 25 | -------------------------------------------------------------------------------- /test/fixtures/communities.yml: -------------------------------------------------------------------------------- 1 | sample: 2 | host: sample.qpixel.com 3 | name: Sample 4 | -------------------------------------------------------------------------------- /test/fixtures/flags.yml: -------------------------------------------------------------------------------- 1 | one: 2 | reason: ABCDEF GHIJKL MNOPQR STUVWX YZ 3 | post: answer_two 4 | user: standard_user 5 | community: sample 6 | -------------------------------------------------------------------------------- /test/fixtures/licenses.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | cc_by_sa: 4 | name: CC BY-SA 5 | url: https://creativecommons.org/licenses/by-sa/4.0 6 | default: true 7 | community: sample 8 | enabled: true 9 | 10 | cc_by_nc_sa: 11 | name: CC BY-NC-SA 12 | url: https://creativecommons.org/licenses/by-nc-sa/4.0 13 | default: false 14 | community: sample 15 | enabled: true 16 | 17 | not_in_use: 18 | name: not in use 19 | url: not in use 20 | default: false 21 | community: sample 22 | enabled: true 23 | 24 | disabled: 25 | name: disabled 26 | url: disabled 27 | default: false 28 | community: sample 29 | enabled: false 30 | -------------------------------------------------------------------------------- /test/fixtures/mod_warnings.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | first_warning: 4 | community_user: sample_standard_user 5 | body: NOBODY EXPECTS THE SPANISH INQUISITION 6 | is_suspension: false 7 | active: false 8 | author: moderator 9 | 10 | second_warning: 11 | community_user: sample_standard_user 12 | body: NOBODY EXPECTS THE SPANISH INQUISITION! 13 | is_suspension: true 14 | suspension_end: 2000-01-01T00:00:00.000000Z 15 | active: false 16 | author: moderator 17 | 18 | third_warning: 19 | community_user: sample_standard_user 20 | body: NOBODY EXPECTS THE SPANISH INQUISITION!!! 21 | is_suspension: true 22 | suspension_end: 5000-01-01T00:00:00.000000Z 23 | active: false 24 | author: moderator -------------------------------------------------------------------------------- /test/fixtures/notifications.yml: -------------------------------------------------------------------------------- 1 | one: 2 | content: ABCDEF GHIJKL MNOPQR STUVWX YZ 3 | link: / 4 | user: standard_user 5 | community: sample 6 | 7 | two: 8 | content: ABCDEF GHIJKL MNOPQR STUVWX 9 | link: / 10 | user: standard_user 11 | community: sample 12 | -------------------------------------------------------------------------------- /test/fixtures/pinned_links.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/post_flag_types.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/fixtures/post_histories.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/fixtures/post_histories.yml -------------------------------------------------------------------------------- /test/fixtures/post_history_tags.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | post_history: one 5 | tag: one 6 | relationship: MyString 7 | 8 | two: 9 | post_history: two 10 | tag: two 11 | relationship: MyString 12 | -------------------------------------------------------------------------------- /test/fixtures/post_history_types.yml: -------------------------------------------------------------------------------- 1 | initial_revision: 2 | name: initial_revision 3 | description: initial revision -------------------------------------------------------------------------------- /test/fixtures/site_settings.yml: -------------------------------------------------------------------------------- 1 | one: 2 | name: ABCDEF 3 | value: ABCDEF GHIJKL 4 | value_type: string 5 | 6 | sanitize: 7 | name: AskingGuidance 8 | value: "" 9 | value_type: string 10 | -------------------------------------------------------------------------------- /test/fixtures/suspicious_votes.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/fixtures/suspicious_votes.yml -------------------------------------------------------------------------------- /test/fixtures/tag_sets.yml: -------------------------------------------------------------------------------- 1 | main: 2 | name: Main 3 | community: sample 4 | 5 | meta: 6 | name: Meta 7 | community: sample 8 | -------------------------------------------------------------------------------- /test/fixtures/tags.yml: -------------------------------------------------------------------------------- 1 | discussion: 2 | name: discussion 3 | community: sample 4 | tag_set: main 5 | 6 | support: 7 | name: support 8 | community: sample 9 | tag_set: main 10 | 11 | bug: 12 | name: bug 13 | community: sample 14 | tag_set: main 15 | 16 | feature-request: 17 | name: feature-request 18 | community: sample 19 | tag_set: main 20 | 21 | faq: 22 | name: faq 23 | community: sample 24 | tag_set: meta 25 | 26 | status-completed: 27 | name: status-completed 28 | community: sample 29 | tag_set: meta 30 | 31 | topic: 32 | name: topic-tag 33 | community: sample 34 | tag_set: main 35 | 36 | child: 37 | name: child-tag 38 | community: sample 39 | tag_set: main 40 | parent: topic 41 | -------------------------------------------------------------------------------- /test/fixtures/warning_templates.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | # This model initially had no columns defined. If you add columns to the 4 | # model remove the '{}' from the fixture names and add the columns immediately 5 | # below each fixture, per the syntax in the comments below 6 | # 7 | one: {} 8 | # column: value 9 | # 10 | two: {} 11 | # column: value 12 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/helpers/.keep -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/integration/.keep -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/mailers/.keep -------------------------------------------------------------------------------- /test/mailers/admin_mailer_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AdminMailerTest < ActionMailer::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/mailers/previews/admin_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | # Preview all emails at http://localhost:3000/rails/mailers/admin_mailer 2 | class AdminMailerPreview < ActionMailer::Preview 3 | end 4 | -------------------------------------------------------------------------------- /test/mailers/previews/devise_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | class DeviseMailerPreview < ActionMailer::Preview 2 | def confirmation_instructions 3 | Devise::Mailer.confirmation_instructions(User.first, 'faketoken') 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/mailers/previews/subscription_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | # Preview all emails at http://localhost:3000/rails/mailers/subscription_mailer 2 | class SubscriptionMailerPreview < ActionMailer::Preview 3 | def subscription 4 | SubscriptionMailer.with(subscription: Subscription.first).subscription 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/mailers/previews/two_factor_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | # Preview all emails at http://localhost:3000/rails/mailers/two_factor_mailer 2 | class TwoFactorMailerPreview < ActionMailer::Preview 3 | def disable_email_preview 4 | TwoFactorMailer.with(user: User.last, host: 'testhost.codidact.com').disable_email 5 | end 6 | 7 | def login_email_preview 8 | TwoFactorMailer.with(user: User.last, host: 'testhost.codidact.com').login_email 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/mailers/subscription_mailer_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SubscriptionMailerTest < ActionMailer::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/mailers/two_factor_mailer_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TwoFactorMailerTest < ActionMailer::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/test/models/.keep -------------------------------------------------------------------------------- /test/models/ability_queue_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AbilityQueueTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/ability_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AbilityTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/audit_log_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AuditLogTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/blocked_item_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class BlockedItemTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/category_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CategoryTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/comment_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CommentTest < ActiveSupport::TestCase 4 | include CommunityRelatedHelper 5 | 6 | test 'is post related' do 7 | assert_post_related(Comment) 8 | end 9 | 10 | test 'parent_question should return question for a comment on an answer' do 11 | assert_equal posts(:question_one).id, comments(:on_answer).parent_question.id 12 | end 13 | 14 | test 'parent_question should return nil for a comment on a question' do 15 | assert_nil comments(:one).parent_question 16 | end 17 | 18 | test 'root should return question for comments on any post' do 19 | assert_equal posts(:question_one).id, comments(:one).root.id 20 | assert_equal posts(:question_one).id, comments(:on_answer).root.id 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/models/error_log_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ErrorLogTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/flag_status_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FlagStatusTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/flag_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FlagTest < ActiveSupport::TestCase 4 | include CommunityRelatedHelper 5 | 6 | test 'is post related' do 7 | assert_post_related(Flag) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/models/license_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class LicenseTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/mod_warning_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ModWarningTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/notification_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class NotificationTest < ActiveSupport::TestCase 4 | include CommunityRelatedHelper 5 | 6 | test 'is commmunity related' do 7 | assert_community_related(Notification) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/models/pinned_link_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PinnedLinkTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/post_flag_type_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PostFlagTypeTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/post_history_tag_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PostHistoryTagTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/post_history_type_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class PostHistoryTypeTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/suggested_edit_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SuggestedEditTest < ActiveSupport::TestCase 4 | include CommunityRelatedHelper 5 | 6 | test 'is commmunity related' do 7 | assert_community_related(SuggestedEdit) 8 | end 9 | 10 | test 'is post related' do 11 | assert_post_related(SuggestedEdit) 12 | end 13 | 14 | test 'status helpers work correctly' do 15 | assert suggested_edits(:pending_suggested_edit).pending? 16 | assert suggested_edits(:accepted_suggested_edit).approved? 17 | assert suggested_edits(:rejected_suggested_edit).rejected? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/models/suspicious_vote_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SuspiciousVoteTest < ActiveSupport::TestCase 4 | test 'check_for_vote_fraud should not throw exceptions' do 5 | assert_nothing_raised do 6 | SuspiciousVote.check_for_vote_fraud 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/models/tag_set_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TagSetTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/tag_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TagTest < ActiveSupport::TestCase 4 | include CommunityRelatedHelper 5 | 6 | test 'is community related' do 7 | assert_community_related(Tag) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/models/user_ability_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UserAbilityTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/warning_template_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class WarningTemplateTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/support/application_test_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationTestHelper 2 | def assert_array_equal(expected, object) 3 | [:include?, :each, :size].each do |method| 4 | assert expected.respond_to? method, "Expected `expected' to be array-like, got #{expected.class}" 5 | assert object.respond_to? method, "Expected `object' to be array-like, got #{object.class}" 6 | end 7 | 8 | assert expected.size == object.size, "Array sizes are unequal\n+++#{object}\n---#{expected}" 9 | expected.each do |i| 10 | assert object.include?(i), "Arrays are not equal: missing item #{i}\n+++#{object}\n---#{expected}" 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/support/community_related_helper.rb: -------------------------------------------------------------------------------- 1 | module CommunityRelatedHelper 2 | def assert_community_related(model) 3 | assert model.reflections['community'].present?, 'Community association missing' 4 | assert_equal model.new.community, RequestContext.community, 'Default scope should use context community' 5 | quoted = model.connection.quote_column_name('community_id') 6 | assert model.all.to_sql.include?("#{quoted} = #{RequestContext.community_id}"), 7 | 'Default scope should use context community' 8 | end 9 | 10 | def assert_post_related(model) 11 | assert model.reflections['post'].present?, 'Post association missing' 12 | assert_community_related(model) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtOfCode-/qpixel/d60ba96534310fbaa0ecf9224bcd1e76137f8e78/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------