For the HashAlignment rule, we're using the default `key` style (keys are aligned and values aren't) instead of the `table` style (both keys and values are aligned) because, even if we used both in the application, we used the `key` style a lot more. Furthermore, the `table` style looks strange in places where there are both very long and very short keys and sometimes we weren't even consistent with the `table` style, aligning some keys without aligning other keys. Ideally we could align hashes to "either key or table", so developers can decide whether keeping the symmetry of the code is worth it in a case-per-case basis, but Rubocop doesn't allow this option.
234 lines
7.9 KiB
Ruby
234 lines
7.9 KiB
Ruby
class Setting < ApplicationRecord
|
|
validates :key, presence: true, uniqueness: true
|
|
|
|
default_scope { order(id: :asc) }
|
|
|
|
def prefix
|
|
key.split(".").first
|
|
end
|
|
|
|
def type
|
|
if %w[feature process proposals map html homepage uploads sdg machine_learning].include? prefix
|
|
prefix
|
|
elsif %w[remote_census].include? prefix
|
|
key.rpartition(".").first
|
|
else
|
|
"configuration"
|
|
end
|
|
end
|
|
|
|
def enabled?
|
|
value.present?
|
|
end
|
|
|
|
def content_type?
|
|
key.split(".").last == "content_types"
|
|
end
|
|
|
|
def content_type_group
|
|
key.split(".").second
|
|
end
|
|
|
|
class << self
|
|
def [](key)
|
|
where(key: key).pick(:value).presence
|
|
end
|
|
|
|
def []=(key, value)
|
|
setting = find_by(key: key) || new(key: key)
|
|
setting.value = value.presence
|
|
setting.save!
|
|
end
|
|
|
|
def rename_key(from:, to:)
|
|
if where(key: to).empty?
|
|
value = where(key: from).pick(:value).presence
|
|
create!(key: to, value: value)
|
|
end
|
|
remove(from)
|
|
end
|
|
|
|
def remove(key)
|
|
setting = find_by(key: key)
|
|
setting.destroy if setting.present?
|
|
end
|
|
|
|
def accepted_content_types_for(group)
|
|
mime_content_types = Setting["uploads.#{group}.content_types"]&.split(" ") || []
|
|
Setting.mime_types[group].select { |_, content_type| mime_content_types.include?(content_type) }.keys
|
|
end
|
|
|
|
def mime_types
|
|
{
|
|
"images" => {
|
|
"jpg" => "image/jpeg",
|
|
"png" => "image/png",
|
|
"gif" => "image/gif"
|
|
},
|
|
"documents" => {
|
|
"pdf" => "application/pdf",
|
|
"doc" => "application/msword",
|
|
"docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
"xls" => "application/x-ole-storage",
|
|
"xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
"csv" => "text/plain",
|
|
"zip" => "application/zip"
|
|
}
|
|
}
|
|
end
|
|
|
|
def defaults
|
|
{
|
|
"feature.featured_proposals": nil,
|
|
"feature.facebook_login": true,
|
|
"feature.google_login": true,
|
|
"feature.twitter_login": true,
|
|
"feature.wordpress_login": false,
|
|
"feature.public_stats": true,
|
|
"feature.signature_sheets": true,
|
|
"feature.user.recommendations": true,
|
|
"feature.user.recommendations_on_debates": true,
|
|
"feature.user.recommendations_on_proposals": true,
|
|
"feature.user.skip_verification": "true",
|
|
"feature.community": true,
|
|
"feature.map": nil,
|
|
"feature.allow_attached_documents": true,
|
|
"feature.allow_images": true,
|
|
"feature.help_page": true,
|
|
"feature.remote_translations": nil,
|
|
"feature.translation_interface": nil,
|
|
"feature.remote_census": nil,
|
|
"feature.valuation_comment_notification": true,
|
|
"feature.graphql_api": true,
|
|
"feature.sdg": true,
|
|
"feature.machine_learning": false,
|
|
"feature.remove_investments_supports": true,
|
|
"homepage.widgets.feeds.debates": true,
|
|
"homepage.widgets.feeds.processes": true,
|
|
"homepage.widgets.feeds.proposals": true,
|
|
# Code to be included at the top (inside <body>) of every page
|
|
"html.per_page_code_body": "",
|
|
# Code to be included at the top (inside <head>) of every page (useful for tracking)
|
|
"html.per_page_code_head": "",
|
|
"map.latitude": 51.48,
|
|
"map.longitude": 0.0,
|
|
"map.zoom": 10,
|
|
"process.debates": true,
|
|
"process.proposals": true,
|
|
"process.polls": true,
|
|
"process.budgets": true,
|
|
"process.legislation": true,
|
|
"proposals.successful_proposal_id": nil,
|
|
"proposals.poll_short_title": nil,
|
|
"proposals.poll_description": nil,
|
|
"proposals.poll_link": nil,
|
|
"proposals.email_short_title": nil,
|
|
"proposals.email_description": nil,
|
|
"proposals.poster_short_title": nil,
|
|
"proposals.poster_description": nil,
|
|
# Images and Documents
|
|
"uploads.images.title.min_length": 4,
|
|
"uploads.images.title.max_length": 80,
|
|
"uploads.images.min_width": 0,
|
|
"uploads.images.min_height": 475,
|
|
"uploads.images.max_size": 1,
|
|
"uploads.images.content_types": "image/jpeg",
|
|
"uploads.documents.max_amount": 3,
|
|
"uploads.documents.max_size": 3,
|
|
"uploads.documents.content_types": "application/pdf",
|
|
# Names for the moderation console, as a hint for moderators
|
|
# to know better how to assign users with official positions
|
|
"official_level_1_name": I18n.t("seeds.settings.official_level_1_name"),
|
|
"official_level_2_name": I18n.t("seeds.settings.official_level_2_name"),
|
|
"official_level_3_name": I18n.t("seeds.settings.official_level_3_name"),
|
|
"official_level_4_name": I18n.t("seeds.settings.official_level_4_name"),
|
|
"official_level_5_name": I18n.t("seeds.settings.official_level_5_name"),
|
|
"max_ratio_anon_votes_on_debates": 50,
|
|
"max_votes_for_debate_edit": 1000,
|
|
"max_votes_for_proposal_edit": 1000,
|
|
"comments_body_max_length": 1000,
|
|
"proposal_code_prefix": "CONSUL",
|
|
"votes_for_proposal_success": 10000,
|
|
"months_to_archive_proposals": 12,
|
|
# Users with this email domain will automatically be marked as level 1 officials
|
|
# Emails under the domain's subdomains will also be included
|
|
"email_domain_for_officials": "",
|
|
"facebook_handle": nil,
|
|
"instagram_handle": nil,
|
|
"telegram_handle": nil,
|
|
"twitter_handle": nil,
|
|
"twitter_hashtag": nil,
|
|
"youtube_handle": nil,
|
|
"org_name": default_org_name,
|
|
"meta_title": nil,
|
|
"meta_description": nil,
|
|
"meta_keywords": nil,
|
|
"proposal_notification_minimum_interval_in_days": 3,
|
|
"direct_message_max_per_day": 3,
|
|
"mailer_from_name": default_org_name,
|
|
"mailer_from_address": default_mailer_from_address,
|
|
"min_age_to_participate": 16,
|
|
"hot_score_period_in_days": 31,
|
|
"related_content_score_threshold": -0.3,
|
|
"featured_proposals_number": 3,
|
|
"feature.dashboard.notification_emails": nil,
|
|
"machine_learning.comments_summary": false,
|
|
"machine_learning.related_content": false,
|
|
"machine_learning.tags": false,
|
|
"postal_codes": "",
|
|
"remote_census.general.endpoint": "",
|
|
"remote_census.request.method_name": "",
|
|
"remote_census.request.structure": "",
|
|
"remote_census.request.document_type": "",
|
|
"remote_census.request.document_number": "",
|
|
"remote_census.request.date_of_birth": "",
|
|
"remote_census.request.postal_code": "",
|
|
"remote_census.response.date_of_birth": "",
|
|
"remote_census.response.postal_code": "",
|
|
"remote_census.response.district": "",
|
|
"remote_census.response.gender": "",
|
|
"remote_census.response.name": "",
|
|
"remote_census.response.surname": "",
|
|
"remote_census.response.valid": "",
|
|
"sdg.process.debates": true,
|
|
"sdg.process.proposals": true,
|
|
"sdg.process.polls": true,
|
|
"sdg.process.budgets": true,
|
|
"sdg.process.legislation": true
|
|
}
|
|
end
|
|
|
|
def default_org_name
|
|
Tenant.current&.name || default_main_org_name
|
|
end
|
|
|
|
def default_main_org_name
|
|
"CONSUL DEMOCRACY"
|
|
end
|
|
|
|
def default_mailer_from_address
|
|
"noreply@#{Tenant.current_host.presence || "consuldemocracy.dev"}"
|
|
end
|
|
|
|
def reset_defaults
|
|
defaults.each { |name, value| self[name] = value }
|
|
end
|
|
|
|
def add_new_settings
|
|
defaults.each do |name, value|
|
|
self[name] = value unless find_by(key: name)
|
|
end
|
|
end
|
|
|
|
def force_presence_date_of_birth?
|
|
Setting["feature.remote_census"].present? &&
|
|
Setting["remote_census.request.date_of_birth"].present?
|
|
end
|
|
|
|
def force_presence_postal_code?
|
|
Setting["feature.remote_census"].present? &&
|
|
Setting["remote_census.request.postal_code"].present?
|
|
end
|
|
end
|
|
end
|