Commit iniziale di eminuxCRM: CRM Rails con pipeline, campagne email e Docker.
Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
require_relative "boot"
|
||||
|
||||
require "rails"
|
||||
require "active_model/railtie"
|
||||
require "active_job/railtie"
|
||||
require "active_record/railtie"
|
||||
require "active_storage/engine"
|
||||
require "action_controller/railtie"
|
||||
require "action_mailer/railtie"
|
||||
require "action_view/railtie"
|
||||
require "action_cable/engine"
|
||||
require "action_text/trix"
|
||||
require "rails/test_unit/railtie"
|
||||
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Simplecrm
|
||||
class Application < Rails::Application
|
||||
config.load_defaults 8.1
|
||||
config.autoload_lib(ignore: %w[assets tasks])
|
||||
config.time_zone = "Europe/Rome"
|
||||
config.i18n.default_locale = :it
|
||||
config.i18n.available_locales = %i[it en]
|
||||
config.generators.system_tests = nil
|
||||
config.x.app_name = "eminuxCRM"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
require "bundler/setup" # Set up gems listed in the Gemfile.
|
||||
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Audit all gems listed in the Gemfile for known security problems by running bin/bundler-audit.
|
||||
# CVEs that are not relevant to the application can be enumerated on the ignore list below.
|
||||
|
||||
ignore:
|
||||
- CVE-THAT-DOES-NOT-APPLY
|
||||
@@ -0,0 +1,10 @@
|
||||
development:
|
||||
adapter: async
|
||||
|
||||
test:
|
||||
adapter: test
|
||||
|
||||
production:
|
||||
adapter: redis
|
||||
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
|
||||
channel_prefix: app_production
|
||||
@@ -0,0 +1,20 @@
|
||||
# Run using bin/ci
|
||||
|
||||
CI.run do
|
||||
step "Setup", "bin/setup --skip-server"
|
||||
|
||||
step "Style: Ruby", "bin/rubocop"
|
||||
|
||||
step "Security: Gem audit", "bin/bundler-audit"
|
||||
step "Security: Importmap vulnerability audit", "bin/importmap audit"
|
||||
step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error"
|
||||
|
||||
|
||||
# Optional: set a green GitHub commit status to unblock PR merge.
|
||||
# Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`.
|
||||
# if success?
|
||||
# step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff"
|
||||
# else
|
||||
# failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again."
|
||||
# end
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
5NspSSxWg4jYdRx5haY2znA/ik7gtI/quqyi/kkr+ilHOgwKhRyzQR2dS3ibSktDADY0BQh8V8Wd5aDH2sIRwo4hDKpT5ptmVNfEVUMjS8bpONxHxz1CchuyynpLp4COvu1Osnfbn4XZn9djx3rVJucq1/11ImlmthmieZP7oPCyMLOaB73EtIkgSqlwKGEaq8X1BleZzl6DvwA8/airYLjACIgycBeG2r8zdcTI/SKTI82BYxIFRXOccf+YPE3fNCefTi9ymNTne9eaQhBNXf4knaShXCokqawPLgZDc3rqSKaaIm15HdLC25OQBX57GbBAXj2PbC8wl1BbYh10ajXXFXaW8JiboA0cJdbBlMY8RTkUFsrgjgXg6MNnf/hbw6svVAdQYUueC8MRZXM/z99aRiSEdAzz4MqlQL/Hlh9s2VHHmy270PfVc/q+kVyJBZBRJbkwqlr3XLHyk1tWhofsYUNKt5vvZhzcnuXYCM5dnhorBQ5P34nH--nFSjTb/kdgiBtBhY--FI3OFfoWUpmlQu9RsHGqUQ==
|
||||
@@ -0,0 +1,22 @@
|
||||
# PostgreSQL
|
||||
default: &default
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
||||
host: <%= ENV.fetch("DATABASE_HOST", "localhost") %>
|
||||
port: <%= ENV.fetch("DATABASE_PORT", 5432) %>
|
||||
username: <%= ENV.fetch("POSTGRES_USER", "simplecrm") %>
|
||||
password: <%= ENV.fetch("POSTGRES_PASSWORD", "simplecrm_dev") %>
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: <%= ENV.fetch("POSTGRES_DB", "simplecrm_development") %>
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
database: simplecrm_test
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
database: <%= ENV.fetch("POSTGRES_DB", "simplecrm_production") %>
|
||||
url: <%= ENV["DATABASE_URL"] %>
|
||||
@@ -0,0 +1,5 @@
|
||||
# Load the Rails application.
|
||||
require_relative "application"
|
||||
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
@@ -0,0 +1,84 @@
|
||||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Make code changes take effect immediately without server restart.
|
||||
config.enable_reloading = true
|
||||
|
||||
# Do not eager load code on boot.
|
||||
config.eager_load = false
|
||||
|
||||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
# Enable server timing.
|
||||
config.server_timing = true
|
||||
|
||||
# Enable/disable Action Controller caching. By default Action Controller caching is disabled.
|
||||
# Run rails dev:cache to toggle Action Controller caching.
|
||||
if Rails.root.join("tmp/caching-dev.txt").exist?
|
||||
config.action_controller.perform_caching = true
|
||||
config.action_controller.enable_fragment_cache_logging = true
|
||||
config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" }
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
end
|
||||
|
||||
# Change to :null_store to avoid any caching.
|
||||
config.cache_store = :memory_store
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options).
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Make template changes take effect immediately.
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Set localhost to be used by links generated in mailer templates.
|
||||
config.action_mailer.default_url_options = {
|
||||
host: ENV.fetch("APP_HOST", "localhost"),
|
||||
port: ENV.fetch("APP_PORT", 3000)
|
||||
}
|
||||
|
||||
config.active_job.queue_adapter = :async
|
||||
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
# Append comments with runtime information tags to SQL queries in logs.
|
||||
config.active_record.query_log_tags_enabled = true
|
||||
|
||||
# Highlight code that enqueued background job in logs.
|
||||
config.active_job.verbose_enqueue_logs = true
|
||||
|
||||
# Highlight code that triggered redirect in logs.
|
||||
config.action_dispatch.verbose_redirect_logs = true
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = true
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
# Uncomment if you wish to allow Action Cable access from any origin.
|
||||
# config.action_cable.disable_request_forgery_protection = true
|
||||
|
||||
# Raise error when a before_action's only/except options reference missing actions.
|
||||
config.action_controller.raise_on_missing_callback_actions = true
|
||||
|
||||
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
|
||||
# config.generators.apply_rubocop_autocorrect_after_generate!
|
||||
end
|
||||
@@ -0,0 +1,106 @@
|
||||
require "active_support/core_ext/integer/time"
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.enable_reloading = false
|
||||
|
||||
# Eager load code on boot for better performance and memory savings (ignored by Rake tasks).
|
||||
config.eager_load = true
|
||||
|
||||
# Full error reports are disabled.
|
||||
config.consider_all_requests_local = false
|
||||
|
||||
# Turn on fragment caching in view templates.
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
# Cache assets for far-future expiry since they are all digest stamped.
|
||||
config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||
# config.asset_host = "http://assets.example.com"
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options).
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Assume SSL quando il TLS termina sul reverse proxy (NPM) e inoltra X-Forwarded-Proto.
|
||||
# Separato da force_ssl per non rompere healthcheck HTTP su :3000.
|
||||
config.assume_ssl = ENV["ASSUME_SSL"] == "true" || ENV["FORCE_SSL"] == "true"
|
||||
|
||||
# Force SSL only when FORCE_SSL=true (LAN/HTTP o TLS su NPM: lasciare disabilitato).
|
||||
config.force_ssl = ENV["FORCE_SSL"] == "true"
|
||||
|
||||
# Skip http-to-https redirect for the default health check endpoint.
|
||||
# config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
|
||||
|
||||
# Log to STDOUT with the current request id as a default log tag.
|
||||
config.log_tags = [ :request_id ]
|
||||
config.logger = ActiveSupport::TaggedLogging.logger(STDOUT)
|
||||
|
||||
# Change to "debug" to log everything (including potentially personally-identifiable information!).
|
||||
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
|
||||
|
||||
# Prevent health checks from clogging up the logs.
|
||||
config.silence_healthcheck_path = "/up"
|
||||
|
||||
# Don't log any deprecations.
|
||||
config.active_support.report_deprecations = false
|
||||
|
||||
# Replace the default in-process memory cache store with a durable alternative.
|
||||
# config.cache_store = :mem_cache_store
|
||||
|
||||
# Replace the default in-process and non-durable queuing backend for Active Job.
|
||||
# config.active_job.queue_adapter = :resque
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Set host to be used by links generated in mailer templates.
|
||||
config.action_mailer.default_url_options = {
|
||||
host: ENV.fetch("APP_HOST", "localhost"),
|
||||
port: ENV["APP_PORT"].presence&.to_i
|
||||
}.compact
|
||||
|
||||
# Host authorization: allow configured hosts (comma-separated) or clear for LAN.
|
||||
if ENV["RAILS_ALLOWED_HOSTS"].present?
|
||||
config.hosts.clear
|
||||
ENV["RAILS_ALLOWED_HOSTS"].split(",").map(&:strip).each { |h| config.hosts << h }
|
||||
else
|
||||
config.hosts.clear
|
||||
end
|
||||
# Healthcheck Docker e reverse proxy interni
|
||||
config.hosts << "localhost"
|
||||
config.hosts << "127.0.0.1"
|
||||
config.hosts << "web"
|
||||
config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
|
||||
|
||||
# Specify outgoing SMTP server. Remember to add smtp/* credentials via bin/rails credentials:edit.
|
||||
# config.action_mailer.smtp_settings = {
|
||||
# user_name: Rails.application.credentials.dig(:smtp, :user_name),
|
||||
# password: Rails.application.credentials.dig(:smtp, :password),
|
||||
# address: "smtp.example.com",
|
||||
# port: 587,
|
||||
# authentication: :plain
|
||||
# }
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
|
||||
# Only use :id for inspections in production.
|
||||
config.active_record.attributes_for_inspect = [ :id ]
|
||||
|
||||
# Enable DNS rebinding protection and other `Host` header attacks.
|
||||
# config.hosts = [
|
||||
# "example.com", # Allow requests from example.com
|
||||
# /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
|
||||
# ]
|
||||
#
|
||||
# Skip DNS rebinding protection for the default health check endpoint.
|
||||
# config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
# and recreated between test runs. Don't rely on the data there!
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# While tests run files are not watched, reloading is not necessary.
|
||||
config.enable_reloading = false
|
||||
|
||||
# Eager loading loads your entire application. When running a single test locally,
|
||||
# this is usually not necessary, and can slow down your test suite. However, it's
|
||||
# recommended that you enable it in continuous integration systems to ensure eager
|
||||
# loading is working properly before deploying your code.
|
||||
config.eager_load = ENV["CI"].present?
|
||||
|
||||
# Configure public file server for tests with cache-control for performance.
|
||||
config.public_file_server.headers = { "cache-control" => "public, max-age=3600" }
|
||||
|
||||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
config.cache_store = :null_store
|
||||
|
||||
# Render exception templates for rescuable exceptions and raise for other exceptions.
|
||||
config.action_dispatch.show_exceptions = :rescuable
|
||||
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
# Store uploaded files on the local file system in a temporary directory.
|
||||
config.active_storage.service = :test
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
# The :test delivery method accumulates sent emails in the
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Set host to be used by links generated in mailer templates.
|
||||
config.action_mailer.default_url_options = { host: "example.com" }
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
# Raise error when a before_action's only/except options reference missing actions.
|
||||
config.action_controller.raise_on_missing_callback_actions = true
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
# Pin npm packages by running ./bin/importmap
|
||||
|
||||
pin "application"
|
||||
pin "trix"
|
||||
pin "@hotwired/turbo-rails", to: "turbo.min.js"
|
||||
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
||||
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||
@@ -0,0 +1,25 @@
|
||||
# Chiavi derivate da SECRET_KEY_BASE così le password SMTP restano cifrate
|
||||
# anche senza rails credentials:edit (Docker / deploy).
|
||||
#
|
||||
# In Rails 8 il getter di ActiveRecord::Encryption.config.primary_key solleva
|
||||
# se la chiave manca: non usare ||= su quell'oggetto.
|
||||
require "digest"
|
||||
|
||||
secret = Rails.application.secret_key_base.to_s
|
||||
keys = {
|
||||
primary_key: Digest::SHA256.hexdigest("#{secret}/ar-enc-primary"),
|
||||
deterministic_key: Digest::SHA256.hexdigest("#{secret}/ar-enc-deterministic"),
|
||||
key_derivation_salt: Digest::SHA256.hexdigest("#{secret}/ar-enc-salt")
|
||||
}
|
||||
|
||||
cfg = Rails.application.config.active_record.encryption
|
||||
keys.each { |name, value| cfg[name] = value }
|
||||
cfg.support_unencrypted_data = true
|
||||
|
||||
Rails.application.config.after_initialize do
|
||||
enc = ActiveRecord::Encryption.config
|
||||
enc.primary_key = keys[:primary_key]
|
||||
enc.deterministic_key = keys[:deterministic_key]
|
||||
enc.key_derivation_salt = keys[:key_derivation_salt]
|
||||
enc.support_unencrypted_data = true
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = "1.0"
|
||||
|
||||
# Add additional assets to the asset load path.
|
||||
# Rails.application.config.assets.paths << Emoji.images_path
|
||||
@@ -0,0 +1,29 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Define an application-wide content security policy.
|
||||
# See the Securing Rails Applications Guide for more information:
|
||||
# https://guides.rubyonrails.org/security.html#content-security-policy-header
|
||||
|
||||
# Rails.application.configure do
|
||||
# config.content_security_policy do |policy|
|
||||
# policy.default_src :self, :https
|
||||
# policy.font_src :self, :https, :data
|
||||
# policy.img_src :self, :https, :data
|
||||
# policy.object_src :none
|
||||
# policy.script_src :self, :https
|
||||
# policy.style_src :self, :https
|
||||
# # Specify URI for violation reports
|
||||
# # policy.report_uri "/csp-violation-report-endpoint"
|
||||
# end
|
||||
#
|
||||
# # Generate session nonces for permitted importmap, inline scripts, and inline styles.
|
||||
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
|
||||
# config.content_security_policy_nonce_directives = %w(script-src style-src)
|
||||
#
|
||||
# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`
|
||||
# # if the corresponding directives are specified in `content_security_policy_nonce_directives`.
|
||||
# # config.content_security_policy_nonce_auto = true
|
||||
#
|
||||
# # Report violations without enforcing the policy.
|
||||
# # config.content_security_policy_report_only = true
|
||||
# end
|
||||
@@ -0,0 +1,8 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
|
||||
# Use this to limit dissemination of sensitive information.
|
||||
# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
|
||||
Rails.application.config.filter_parameters += [
|
||||
:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new inflection rules using the following format. Inflections
|
||||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, "\\1en"
|
||||
# inflect.singular /^(ox)en/i, "\\1"
|
||||
# inflect.irregular "person", "people"
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
|
||||
# These inflection rules are supported but not enabled by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.acronym "RESTful"
|
||||
# end
|
||||
@@ -0,0 +1,5 @@
|
||||
require "pagy"
|
||||
require "pagy/extras/overflow"
|
||||
|
||||
Pagy::DEFAULT[:limit] = 25
|
||||
Pagy::DEFAULT[:overflow] = :empty_page
|
||||
@@ -0,0 +1,12 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
#
|
||||
# Cookie Secure solo con FORCE_SSL/SESSION_COOKIE_SECURE.
|
||||
# Dietro NPM→Caddy→Rails (HTTP interno) request.ssl? è false: con secure:true
|
||||
# Rails non emette _simplecrm_session → CSRF 422 al login su HTTPS.
|
||||
secure_cookie = ENV["FORCE_SSL"] == "true" || ENV["SESSION_COOKIE_SECURE"] == "true"
|
||||
|
||||
Rails.application.config.session_store :cookie_store,
|
||||
key: "_simplecrm_session",
|
||||
secure: secure_cookie,
|
||||
httponly: true,
|
||||
same_site: :lax
|
||||
@@ -0,0 +1,31 @@
|
||||
# Files in the config/locales directory are used for internationalization and
|
||||
# are automatically loaded by Rails. If you want to use locales other than
|
||||
# English, add the necessary files in this directory.
|
||||
#
|
||||
# To use the locales, use `I18n.t`:
|
||||
#
|
||||
# I18n.t "hello"
|
||||
#
|
||||
# In views, this is aliased to just `t`:
|
||||
#
|
||||
# <%= t("hello") %>
|
||||
#
|
||||
# To use a different locale, set it with `I18n.locale`:
|
||||
#
|
||||
# I18n.locale = :es
|
||||
#
|
||||
# This would use the information in config/locales/es.yml.
|
||||
#
|
||||
# To learn more about the API, please read the Rails Internationalization guide
|
||||
# at https://guides.rubyonrails.org/i18n.html.
|
||||
#
|
||||
# Be aware that YAML interprets the following case-insensitive strings as
|
||||
# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
|
||||
# must be quoted to be interpreted as strings. For example:
|
||||
#
|
||||
# en:
|
||||
# "yes": yup
|
||||
# enabled: "ON"
|
||||
|
||||
en:
|
||||
hello: "Hello world"
|
||||
@@ -0,0 +1,143 @@
|
||||
it:
|
||||
date:
|
||||
formats:
|
||||
default: "%d/%m/%Y"
|
||||
long: "%d %B %Y"
|
||||
short: "%d/%m/%Y"
|
||||
day_names: [domenica, lunedì, martedì, mercoledì, giovedì, venerdì, sabato]
|
||||
abbr_day_names: [dom, lun, mar, mer, gio, ven, sab]
|
||||
month_names: [~, gennaio, febbraio, marzo, aprile, maggio, giugno, luglio, agosto, settembre, ottobre, novembre, dicembre]
|
||||
abbr_month_names: [~, gen, feb, mar, apr, mag, giu, lug, ago, set, ott, nov, dic]
|
||||
time:
|
||||
formats:
|
||||
default: "%d/%m/%Y %H:%M"
|
||||
short: "%d/%m/%Y %H:%M"
|
||||
long: "%d %B %Y %H:%M"
|
||||
am: "am"
|
||||
pm: "pm"
|
||||
number:
|
||||
currency:
|
||||
format:
|
||||
unit: "€"
|
||||
separator: ","
|
||||
delimiter: "."
|
||||
format: "%n %u"
|
||||
activerecord:
|
||||
models:
|
||||
organization: Organizzazione
|
||||
contact: Contatto
|
||||
opportunity: Opportunità
|
||||
task: Task
|
||||
activity: Attività
|
||||
user: Utente
|
||||
sales_goal: Obiettivo
|
||||
mail_identity: Account email
|
||||
mail_template: Template email
|
||||
mailing: Invio email
|
||||
mailing_recipient: Destinatario
|
||||
attributes:
|
||||
organization:
|
||||
name: Nome
|
||||
legal_name: Ragione sociale
|
||||
organization_type: Tipologia
|
||||
sport: Sport
|
||||
country: Paese
|
||||
region: Regione
|
||||
province: Provincia
|
||||
city: Città
|
||||
address: Indirizzo
|
||||
website: Sito / profilo
|
||||
phone: Telefono
|
||||
email: Email verificata
|
||||
vat_number: P. IVA
|
||||
notes: Note follow-up
|
||||
status: Stato
|
||||
lead_source: Fonte
|
||||
assigned_user_id: Owner
|
||||
list_position: N.
|
||||
team_gender: M/F
|
||||
streaming_status: Streaming rilevato
|
||||
commercial_fit: Evidenza / fit commerciale
|
||||
source_url: Fonte contatto / ricerca
|
||||
verified_at: Data verifica
|
||||
contact:
|
||||
first_name: Nome
|
||||
last_name: Cognome
|
||||
role: Ruolo
|
||||
email: Email
|
||||
phone: Telefono
|
||||
mobile: Cellulare
|
||||
preferred_contact_method: Contatto preferito
|
||||
primary_contact: Contatto principale
|
||||
notes: Note
|
||||
opportunity:
|
||||
name: Nome
|
||||
pipeline_stage: Stage
|
||||
estimated_value: Valore stimato
|
||||
probability: Probabilità
|
||||
expected_close_date: Chiusura prevista
|
||||
product: Piano
|
||||
lost_reason: Motivo perdita
|
||||
notes: Note
|
||||
ab_variant: Test A/B
|
||||
send_status: Stato invio
|
||||
sent_on: Data invio
|
||||
outcome: Esito
|
||||
demo_trial: Demo / Trial
|
||||
converted: Conversione
|
||||
task:
|
||||
title: Titolo
|
||||
description: Descrizione
|
||||
due_at: Scadenza
|
||||
priority: Priorità
|
||||
task_type: Tipo
|
||||
status: Stato
|
||||
user:
|
||||
email: Email
|
||||
first_name: Nome
|
||||
last_name: Cognome
|
||||
password: Password
|
||||
password_confirmation: Conferma password
|
||||
role: Ruolo
|
||||
mail_identity:
|
||||
name: Nome account
|
||||
from_name: Nome mittente
|
||||
from_email: Email mittente
|
||||
reply_to: Reply-To
|
||||
smtp_host: Host SMTP
|
||||
smtp_port: Porta
|
||||
smtp_username: Utente SMTP
|
||||
smtp_password: Password SMTP
|
||||
smtp_authentication: Autenticazione
|
||||
encryption: Crittografia
|
||||
verify_ssl: Verifica certificato SSL
|
||||
active: Attivo
|
||||
mail_template:
|
||||
name: Nome
|
||||
subject: Oggetto
|
||||
body_html: Corpo HTML
|
||||
mailing:
|
||||
name: Nome invio
|
||||
subject: Oggetto variante A
|
||||
body_html: Corpo HTML variante A
|
||||
subject_b: Oggetto variante B
|
||||
body_html_b: Corpo HTML variante B
|
||||
audience: Destinatari
|
||||
ab_test: Test A/B
|
||||
ab_assignment: Come assegnare A e B
|
||||
interval_seconds: Pausa tra un invio e l'altro (secondi)
|
||||
mail_identity: Account mittente
|
||||
mail_template: Template A
|
||||
mail_template_b: Template B
|
||||
errors:
|
||||
format: "%{attribute} %{message}"
|
||||
messages:
|
||||
blank: non può essere vuoto
|
||||
taken: è già in uso
|
||||
invalid: non è valido
|
||||
confirmation: non coincide
|
||||
too_short: è troppo corto (minimo %{count} caratteri)
|
||||
helpers:
|
||||
submit:
|
||||
create: Crea
|
||||
update: Salva
|
||||
@@ -0,0 +1,39 @@
|
||||
# This configuration file will be evaluated by Puma. The top-level methods that
|
||||
# are invoked here are part of Puma's configuration DSL. For more information
|
||||
# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html.
|
||||
#
|
||||
# Puma starts a configurable number of processes (workers) and each process
|
||||
# serves each request in a thread from an internal thread pool.
|
||||
#
|
||||
# You can control the number of workers using ENV["WEB_CONCURRENCY"]. You
|
||||
# should only set this value when you want to run 2 or more workers. The
|
||||
# default is already 1. You can set it to `auto` to automatically start a worker
|
||||
# for each available processor.
|
||||
#
|
||||
# The ideal number of threads per worker depends both on how much time the
|
||||
# application spends waiting for IO operations and on how much you wish to
|
||||
# prioritize throughput over latency.
|
||||
#
|
||||
# As a rule of thumb, increasing the number of threads will increase how much
|
||||
# traffic a given process can handle (throughput), but due to CRuby's
|
||||
# Global VM Lock (GVL) it has diminishing returns and will degrade the
|
||||
# response time (latency) of the application.
|
||||
#
|
||||
# The default is set to 3 threads as it's deemed a decent compromise between
|
||||
# throughput and latency for the average Rails application.
|
||||
#
|
||||
# Any libraries that use a connection pool or another resource pool should
|
||||
# be configured to provide at least as many connections as the number of
|
||||
# threads. This includes Active Record's `pool` parameter in `database.yml`.
|
||||
threads_count = ENV.fetch("RAILS_MAX_THREADS", 3)
|
||||
threads threads_count, threads_count
|
||||
|
||||
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
||||
port ENV.fetch("PORT", 3000)
|
||||
|
||||
# Allow puma to be restarted by `bin/rails restart` command.
|
||||
plugin :tmp_restart
|
||||
|
||||
# Specify the PID file. Defaults to tmp/pids/server.pid in development.
|
||||
# In other environments, only set the PID file if requested.
|
||||
pidfile ENV["PIDFILE"] if ENV["PIDFILE"]
|
||||
@@ -0,0 +1,62 @@
|
||||
Rails.application.routes.draw do
|
||||
get "up" => "rails/health#show", as: :rails_health_check
|
||||
|
||||
get "login", to: "sessions#new"
|
||||
post "login", to: "sessions#create"
|
||||
delete "logout", to: "sessions#destroy"
|
||||
|
||||
resource :password, only: %i[edit update]
|
||||
resources :password_resets, only: %i[new create], path: "password_reset" do
|
||||
collection do
|
||||
get ":token/edit", action: :edit, as: :edit
|
||||
patch ":token", action: :update, as: :update
|
||||
end
|
||||
end
|
||||
|
||||
# Launcher: scegli il progetto (istanza CRM)
|
||||
root "home#index"
|
||||
get "impostazioni", to: "admin#show", as: :admin
|
||||
|
||||
# CRUD progetti anche fuori da un'istanza (bootstrap admin)
|
||||
resources :projects, only: %i[create edit update destroy]
|
||||
resources :users, except: %i[show]
|
||||
resources :mail_identities, except: %i[show]
|
||||
|
||||
# Ogni progetto = istanza CRM dedicata
|
||||
scope "/p/:project_code" do
|
||||
get "/", to: "dashboard#show", as: :project_root
|
||||
get "/today", to: "today#show", as: :today
|
||||
get "/pipeline", to: "pipeline#show", as: :pipeline
|
||||
get "/search", to: "search#show", as: :search
|
||||
get "/reports", to: "reports#index", as: :reports
|
||||
get "/settings", to: "settings#show", as: :settings
|
||||
patch "/settings/goal(/:id)", to: "settings#update_goal", as: :update_goal_settings
|
||||
|
||||
resources :organizations do
|
||||
resources :activities, only: %i[create]
|
||||
end
|
||||
resources :contacts
|
||||
resources :opportunities do
|
||||
member do
|
||||
patch :update_stage
|
||||
end
|
||||
end
|
||||
resources :tasks do
|
||||
member do
|
||||
patch :complete
|
||||
end
|
||||
end
|
||||
resources :imports, only: %i[new create]
|
||||
resources :mail_templates, except: %i[show]
|
||||
resources :mail_images, only: %i[create]
|
||||
resources :mailings do
|
||||
member do
|
||||
post :queue
|
||||
post :test_send
|
||||
post :refresh_recipients
|
||||
patch :update_recipients
|
||||
get :preview
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
test:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("tmp/storage") %>
|
||||
|
||||
local:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("storage") %>
|
||||
|
||||
# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
|
||||
# amazon:
|
||||
# service: S3
|
||||
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
|
||||
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
|
||||
# region: us-east-1
|
||||
# bucket: your_own_bucket-<%= Rails.env %>
|
||||
|
||||
# Remember not to checkin your GCS keyfile to a repository
|
||||
# google:
|
||||
# service: GCS
|
||||
# project: your_project
|
||||
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
|
||||
# bucket: your_own_bucket-<%= Rails.env %>
|
||||
|
||||
# mirror:
|
||||
# service: Mirror
|
||||
# primary: local
|
||||
# mirrors: [ amazon, google, microsoft ]
|
||||
Reference in New Issue
Block a user