summaryrefslogtreecommitdiff
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/application.rb48
-rw-r--r--config/database.yml.mysql12
-rw-r--r--config/dependency_decisions.yml32
-rw-r--r--config/environments/development.rb3
-rw-r--r--config/gitlab.teatro.yml85
-rw-r--r--config/gitlab.yml.example29
-rw-r--r--config/initializers/0_post_deployment_migrations.rb12
-rw-r--r--config/initializers/1_settings.rb60
-rw-r--r--config/initializers/5_backend.rb3
-rw-r--r--config/initializers/6_validations.rb29
-rw-r--r--config/initializers/7_redis.rb3
-rw-r--r--config/initializers/ar5_batching.rb41
-rw-r--r--config/initializers/ar_monkey_patch.rb57
-rw-r--r--config/initializers/ar_speed_up_migration_checking.rb18
-rw-r--r--config/initializers/attr_encrypted_no_db_connection.rb25
-rw-r--r--config/initializers/connection_fix.rb2
-rw-r--r--config/initializers/devise.rb26
-rw-r--r--config/initializers/doorkeeper.rb3
-rw-r--r--config/initializers/gitlab_shell_secret_token.rb20
-rw-r--r--config/initializers/gitlab_workhorse_secret.rb8
-rw-r--r--config/initializers/haml.rb7
-rw-r--r--config/initializers/hamlit.rb18
-rw-r--r--config/initializers/health_check.rb1
-rw-r--r--config/initializers/metrics.rb27
-rw-r--r--config/initializers/mime_types.rb11
-rw-r--r--config/initializers/postgresql_limit_fix.rb27
-rw-r--r--config/initializers/rack_attack.rb.example3
-rw-r--r--config/initializers/rack_attack_logging.rb7
-rw-r--r--config/initializers/relative_naming_ci_namespace.rb16
-rw-r--r--config/initializers/request_profiler.rb5
-rw-r--r--config/initializers/routing_draw.rb7
-rw-r--r--config/initializers/secret_token.rb103
-rw-r--r--config/initializers/sentry.rb3
-rw-r--r--config/initializers/session_store.rb4
-rw-r--r--config/initializers/sidekiq.rb46
-rw-r--r--config/initializers/smtp_settings.rb.sample1
-rw-r--r--config/initializers/trusted_proxies.rb25
-rw-r--r--config/locales/en.yml1
-rw-r--r--config/mail_room.yml70
-rw-r--r--config/no_todos_messages.yml11
-rw-r--r--config/resque.yml.example34
-rw-r--r--config/routes.rb818
-rw-r--r--config/routes/admin.rb102
-rw-r--r--config/routes/api.rb2
-rw-r--r--config/routes/ci.rb15
-rw-r--r--config/routes/dashboard.rb27
-rw-r--r--config/routes/development.rb13
-rw-r--r--config/routes/explore.rb16
-rw-r--r--config/routes/git_http.rb37
-rw-r--r--config/routes/group.rb45
-rw-r--r--config/routes/help.rb4
-rw-r--r--config/routes/import.rb42
-rw-r--r--config/routes/profile.rb50
-rw-r--r--config/routes/project.rb315
-rw-r--r--config/routes/repository.rb110
-rw-r--r--config/routes/sherlock.rb12
-rw-r--r--config/routes/sidekiq.rb4
-rw-r--r--config/routes/snippets.rb9
-rw-r--r--config/routes/uploads.rb21
-rw-r--r--config/routes/user.rb45
-rw-r--r--config/routes/wiki.rb16
-rw-r--r--config/sidekiq_queues.yml50
-rw-r--r--config/unicorn.rb.example4
63 files changed, 1623 insertions, 1077 deletions
diff --git a/config/application.rb b/config/application.rb
index 05fec995ed3..fb84870dfbd 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -24,7 +24,8 @@ module Gitlab
#{config.root}/app/models/ci
#{config.root}/app/models/hooks
#{config.root}/app/models/members
- #{config.root}/app/models/project_services))
+ #{config.root}/app/models/project_services
+ #{config.root}/app/workers/concerns))
config.generators.templates.push("#{config.root}/generator_templates")
@@ -50,6 +51,7 @@ module Gitlab
# - Build variables (:variables)
# - GitLab Pages SSL cert/key info (:certificate, :encrypted_key)
# - Webhook URLs (:hook)
+ # - GitLab-shell secret token (:secret_token)
# - Sentry DSN (:sentry_dsn)
# - Deploy keys (:key)
config.filter_parameters += %i(
@@ -62,6 +64,7 @@ module Gitlab
password
password_confirmation
private_token
+ secret_token
sentry_dsn
variables
)
@@ -76,36 +79,65 @@ module Gitlab
# Enable the asset pipeline
config.assets.enabled = true
- config.assets.paths << Gemojione.index.images_path
+ config.assets.paths << Gemojione.images_path
config.assets.precompile << "*.png"
config.assets.precompile << "print.css"
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
- config.assets.precompile << "graphs/application.js"
- config.assets.precompile << "users/application.js"
- config.assets.precompile << "network/application.js"
+ config.assets.precompile << "graphs/graphs_bundle.js"
+ config.assets.precompile << "users/users_bundle.js"
+ config.assets.precompile << "network/network_bundle.js"
+ config.assets.precompile << "profile/profile_bundle.js"
+ config.assets.precompile << "protected_branches/protected_branches_bundle.js"
+ config.assets.precompile << "diff_notes/diff_notes_bundle.js"
+ config.assets.precompile << "boards/boards_bundle.js"
+ config.assets.precompile << "cycle_analytics/cycle_analytics_bundle.js"
+ config.assets.precompile << "merge_conflicts/merge_conflicts_bundle.js"
+ config.assets.precompile << "boards/test_utils/simulate_drag.js"
+ config.assets.precompile << "environments/environments_bundle.js"
+ config.assets.precompile << "blob_edit/blob_edit_bundle.js"
+ config.assets.precompile << "snippet/snippet_bundle.js"
+ config.assets.precompile << "lib/utils/*.js"
+ config.assets.precompile << "lib/*.js"
+ config.assets.precompile << "u2f.js"
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.action_view.sanitized_allowed_protocols = %w(smb)
- config.middleware.use Rack::Attack
+ config.middleware.insert_before Warden::Manager, Rack::Attack
# Allow access to GitLab API from other domains
- config.middleware.use Rack::Cors do
+ config.middleware.insert_before Warden::Manager, Rack::Cors do
+ allow do
+ origins Gitlab.config.gitlab.url
+ resource '/api/*',
+ credentials: true,
+ headers: :any,
+ methods: :any,
+ expose: ['Link']
+ end
+
+ # Cross-origin requests must not have the session cookie available
allow do
origins '*'
resource '/api/*',
+ credentials: false,
headers: :any,
methods: :any,
expose: ['Link']
end
end
- redis_config_hash = Gitlab::Redis.redis_store_options
+ # Use Redis caching across all environments
+ redis_config_hash = Gitlab::Redis.params
redis_config_hash[:namespace] = Gitlab::Redis::CACHE_NAMESPACE
redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
+ if Sidekiq.server? # threaded context
+ redis_config_hash[:pool_size] = Sidekiq.options[:concurrency] + 5
+ redis_config_hash[:pool_timeout] = 1
+ end
config.cache_store = :redis_store, redis_config_hash
config.active_record.raise_in_transactional_callbacks = true
diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index a99c50706c5..d9702870249 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -3,8 +3,8 @@
#
production:
adapter: mysql2
- encoding: utf8
- collation: utf8_general_ci
+ encoding: utf8mb4
+ collation: utf8mb4_general_ci
reconnect: false
database: gitlabhq_production
pool: 10
@@ -18,8 +18,8 @@ production:
#
development:
adapter: mysql2
- encoding: utf8
- collation: utf8_general_ci
+ encoding: utf8mb4
+ collation: utf8mb4_general_ci
reconnect: false
database: gitlabhq_development
pool: 5
@@ -32,8 +32,8 @@ development:
# Do not set this db to the same as development or production.
test: &test
adapter: mysql2
- encoding: utf8
- collation: utf8_general_ci
+ encoding: utf8mb4
+ collation: utf8mb4_general_ci
reconnect: false
database: gitlabhq_test
pool: 5
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 436a2c5e17a..c11296975b7 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -68,6 +68,25 @@
:why: https://opensource.org/licenses/BSD-2-Clause
:versions: []
:when: 2016-05-02 05:55:09.796363000 Z
+- - :whitelist
+ - LGPLv2+
+ - :who: Stan Hu
+ :why: Equivalent to LGPLv2
+ :versions: []
+ :when: 2016-06-07 17:14:10.907682000 Z
+- - :whitelist
+ - Artistic 2.0
+ - :who: Josh Frye
+ :why: Disk/mount information display on Admin pages
+ :versions: []
+ :when: 2016-06-29 16:32:45.432113000 Z
+- - :whitelist
+ - Simplified BSD
+ - :who: Douwe Maan
+ :why: https://opensource.org/licenses/BSD-2-Clause
+ :versions: []
+ :when: 2016-07-26 21:24:07.248480000 Z
+
# LICENSE BLACKLIST
- - :blacklist
@@ -82,6 +101,13 @@
:why: GPL-licensed libraries cannot be linked to from non-GPL projects.
:versions: []
:when: 2016-05-02 05:29:43.904715000 Z
+- - :blacklist
+ - OSL-3.0
+ - :who: Sean McGivern
+ :why: The OSL license is a copyleft license
+ :versions: []
+ :when: 2016-10-28 11:02:15.540105000 Z
+
# GEM LICENSES
- - :license
@@ -175,9 +201,3 @@
:why: https://github.com/jmcnevin/rubypants/blob/master/LICENSE.rdoc
:versions: []
:when: 2016-05-02 05:56:50.696858000 Z
-- - :whitelist
- - LGPLv2+
- - :who: Stan Hu
- :why: Equivalent to LGPLv2
- :versions: []
- :when: 2016-06-07 17:14:10.907682000 Z
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 8cca0039b4a..45a8c1add3e 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -42,4 +42,7 @@ Rails.application.configure do
config.action_mailer.preview_path = 'spec/mailers/previews'
config.eager_load = false
+
+ # Do not log asset requests
+ config.assets.quiet = true
end
diff --git a/config/gitlab.teatro.yml b/config/gitlab.teatro.yml
deleted file mode 100644
index 01c8dc5ff98..00000000000
--- a/config/gitlab.teatro.yml
+++ /dev/null
@@ -1,85 +0,0 @@
-
-production: &base
- gitlab:
- host: localhost
- port: 80
- https: false
-
- user: root
-
- email_from: example@example.com
-
- support_email: support@example.com
-
- default_projects_features:
- issues: true
- merge_requests: true
- wiki: true
- snippets: false
- visibility_level: "private" # can be "private" | "internal" | "public"
-
- issues_tracker:
-
- gravatar:
- enabled: true # Use user avatar image from Gravatar.com (default: true)
-
- ldap:
- enabled: false
- host: '_your_ldap_server'
- port: 636
- uid: 'sAMAccountName'
- method: 'ssl' # "tls" or "ssl" or "plain"
- bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
- password: '_the_password_of_the_bind_user'
- allow_username_or_email_login: true
-
- base: ''
-
- user_filter: ''
-
- omniauth:
- enabled: false
-
- satellites:
- # Relative paths are relative to Rails.root (default: tmp/repo_satellites/)
- path: /apps/gitlab-satellites/
-
- backup:
- path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/)
-
- gitlab_shell:
- path: /apps/gitlab-shell/
-
- # REPOS_PATH MUST NOT BE A SYMLINK!!!
- repos_path: /apps/repositories/
- hooks_path: /apps/gitlab-shell/hooks/
-
- upload_pack: true
- receive_pack: true
-
- git:
- bin_path: /usr/bin/git
- max_size: 5242880 # 5.megabytes
- timeout: 10
-
- extra:
-
-development:
- <<: *base
-
-test:
- <<: *base
- gravatar:
- enabled: true
- gitlab:
- host: localhost
- port: 80
- issues_tracker:
- redmine:
- title: "Redmine"
- project_url: "http://redmine/projects/:issues_tracker_id"
- issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
- new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new"
-
-staging:
- <<: *base
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 75e1a3c1093..327e4a7937c 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -70,6 +70,7 @@ production: &base
email_from: example@example.com
email_display_name: GitLab
email_reply_to: noreply@example.com
+ email_subject_suffix: ''
# Email server smtp settings are in config/initializers/smtp_settings.rb.sample
@@ -106,12 +107,12 @@ production: &base
## Repository downloads directory
# When a user clicks e.g. 'Download zip' on a project, a temporary zip file is created in the following directory.
- # The default is 'tmp/repositories' relative to the root of the Rails app.
- # repository_downloads_path: tmp/repositories
+ # The default is 'shared/cache/archive/' relative to the root of the Rails app.
+ # repository_downloads_path: shared/cache/archive/
## Reply by email
# Allow users to comment on issues and merge requests by replying to notification emails.
- # For documentation on how to set this up, see http://doc.gitlab.com/ce/incoming_email/README.html
+ # For documentation on how to set this up, see http://doc.gitlab.com/ce/administration/reply_by_email.html
incoming_email:
enabled: false
@@ -137,6 +138,8 @@ production: &base
# The mailbox where incoming mail will end up. Usually "inbox".
mailbox: "inbox"
+ # The IDLE command timeout.
+ idle_timeout: 60
## Build Artifacts
artifacts:
@@ -428,6 +431,15 @@ production: &base
satellites:
path: /home/git/gitlab-satellites/
+ ## Repositories settings
+ repositories:
+ # Paths where repositories can be stored. Give the canonicalized absolute pathname.
+ # IMPORTANT: None of the path components may be symlink, because
+ # gitlab-shell invokes Dir.pwd inside the repository path and that results
+ # real path not the symlink.
+ storages: # You must have at least a `default` storage path.
+ default: /home/git/repositories/
+
## Backup settings
backup:
path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/)
@@ -452,9 +464,6 @@ production: &base
## GitLab Shell settings
gitlab_shell:
path: /home/git/gitlab-shell/
-
- # REPOS_PATH MUST NOT BE A SYMLINK!!!
- repos_path: /home/git/repositories/
hooks_path: /home/git/gitlab-shell/hooks/
# File that contains the secret key for verifying access for gitlab-shell.
@@ -528,11 +537,13 @@ test:
# user: YOUR_USERNAME
satellites:
path: tmp/tests/gitlab-satellites/
+ repositories:
+ storages:
+ default: tmp/tests/repositories/
backup:
path: tmp/tests/backups
gitlab_shell:
path: tmp/tests/gitlab-shell/
- repos_path: tmp/tests/repositories/
hooks_path: tmp/tests/gitlab-shell/hooks/
issues_tracker:
redmine:
@@ -540,6 +551,10 @@ test:
project_url: "http://redmine/projects/:issues_tracker_id"
issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new"
+ jira:
+ title: "JIRA"
+ url: https://sample_company.atlasian.net
+ project_key: PROJECT
ldap:
enabled: false
servers:
diff --git a/config/initializers/0_post_deployment_migrations.rb b/config/initializers/0_post_deployment_migrations.rb
new file mode 100644
index 00000000000..0068a03d214
--- /dev/null
+++ b/config/initializers/0_post_deployment_migrations.rb
@@ -0,0 +1,12 @@
+# Post deployment migrations are included by default. This file must be loaded
+# before other initializers as Rails may otherwise memoize a list of migrations
+# excluding the post deployment migrations.
+unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS']
+ path = Rails.root.join('db', 'post_migrate').to_s
+
+ Rails.application.config.paths['db/migrate'] << path
+
+ # Rails memoizes migrations at certain points where it won't read the above
+ # path just yet. As such we must also update the following list of paths.
+ ActiveRecord::Migrator.migrations_paths << path
+end
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index c6dc1e4ab38..9ddd1554811 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -96,7 +96,6 @@ class Settings < Settingslogic
end
end
-
# Default settings
Settings['ldap'] ||= Settingslogic.new({})
Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
@@ -124,7 +123,6 @@ if Settings.ldap['enabled'] || Rails.env.test?
end
end
-
Settings['omniauth'] ||= Settingslogic.new({})
Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil?
Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil?
@@ -188,6 +186,7 @@ Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].ni
Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}"
Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab'
Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}"
+Settings.gitlab['email_subject_suffix'] ||= ENV['GITLAB_EMAIL_SUBJECT_SUFFIX'] || ""
Settings.gitlab['base_url'] ||= Settings.send(:build_base_gitlab_url)
Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url)
Settings.gitlab['user'] ||= 'git'
@@ -213,11 +212,10 @@ Settings.gitlab.default_projects_features['snippets'] = false if Setti
Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
-Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive') if Settings.gitlab['repository_downloads_path'].nil?
-Settings.gitlab['restricted_signup_domains'] ||= []
-Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project]
+Settings.gitlab['domain_whitelist'] ||= []
+Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab google_code fogbugz git gitlab_project]
Settings.gitlab['trusted_proxies'] ||= []
-
+Settings.gitlab['no_todos_messages'] ||= YAML.load_file(Rails.root.join('config', 'no_todos_messages.yml'))
#
# CI
@@ -291,9 +289,28 @@ Settings.cron_jobs['admin_email_worker']['job_class'] = 'AdminEmailWorker'
Settings.cron_jobs['repository_archive_cache_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['repository_archive_cache_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['repository_archive_cache_worker']['job_class'] = 'RepositoryArchiveCacheWorker'
-Settings.cron_jobs['gitlab_remove_project_export_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['gitlab_remove_project_export_worker']['cron'] ||= '0 * * * *'
-Settings.cron_jobs['gitlab_remove_project_export_worker']['job_class'] = 'GitlabRemoveProjectExportWorker'
+Settings.cron_jobs['import_export_project_cleanup_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['import_export_project_cleanup_worker']['cron'] ||= '0 * * * *'
+Settings.cron_jobs['import_export_project_cleanup_worker']['job_class'] = 'ImportExportProjectCleanupWorker'
+Settings.cron_jobs['requests_profiles_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['requests_profiles_worker']['cron'] ||= '0 0 * * *'
+Settings.cron_jobs['requests_profiles_worker']['job_class'] = 'RequestsProfilesWorker'
+Settings.cron_jobs['remove_expired_members_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['remove_expired_members_worker']['cron'] ||= '10 0 * * *'
+Settings.cron_jobs['remove_expired_members_worker']['job_class'] = 'RemoveExpiredMembersWorker'
+Settings.cron_jobs['remove_expired_group_links_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['remove_expired_group_links_worker']['cron'] ||= '10 0 * * *'
+Settings.cron_jobs['remove_expired_group_links_worker']['job_class'] = 'RemoveExpiredGroupLinksWorker'
+Settings.cron_jobs['prune_old_events_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['prune_old_events_worker']['cron'] ||= '* */6 * * *'
+Settings.cron_jobs['prune_old_events_worker']['job_class'] = 'PruneOldEventsWorker'
+
+Settings.cron_jobs['trending_projects_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['trending_projects_worker']['cron'] = '0 1 * * *'
+Settings.cron_jobs['trending_projects_worker']['job_class'] = 'TrendingProjectsWorker'
+Settings.cron_jobs['remove_unreferenced_lfs_objects_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['cron'] ||= '20 0 * * *'
+Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['job_class'] = 'RemoveUnreferencedLfsObjectsWorker'
#
# GitLab Shell
@@ -304,7 +321,6 @@ Settings.gitlab_shell['hooks_path'] ||= Settings.gitlab['user_home'] + '/gitla
Settings.gitlab_shell['secret_file'] ||= Rails.root.join('.gitlab_shell_secret')
Settings.gitlab_shell['receive_pack'] = true if Settings.gitlab_shell['receive_pack'].nil?
Settings.gitlab_shell['upload_pack'] = true if Settings.gitlab_shell['upload_pack'].nil?
-Settings.gitlab_shell['repos_path'] ||= Settings.gitlab['user_home'] + '/repositories/'
Settings.gitlab_shell['ssh_host'] ||= Settings.gitlab.ssh_host
Settings.gitlab_shell['ssh_port'] ||= 22
Settings.gitlab_shell['ssh_user'] ||= Settings.gitlab.user
@@ -312,6 +328,29 @@ Settings.gitlab_shell['owner_group'] ||= Settings.gitlab.user
Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_ssh_path_prefix)
#
+# Repositories
+#
+Settings['repositories'] ||= Settingslogic.new({})
+Settings.repositories['storages'] ||= {}
+# Setting gitlab_shell.repos_path is DEPRECATED and WILL BE REMOVED in version 9.0
+Settings.repositories.storages['default'] ||= Settings.gitlab_shell['repos_path'] || Settings.gitlab['user_home'] + '/repositories/'
+
+#
+# The repository_downloads_path is used to remove outdated repository
+# archives, if someone has it configured incorrectly, and it points
+# to the path where repositories are stored this can cause some
+# data-integrity issue. In this case, we sets it to the default
+# repository_downloads_path value.
+#
+repositories_storages_path = Settings.repositories.storages.values
+repository_downloads_path = Settings.gitlab['repository_downloads_path'].to_s.gsub(/\/$/, '')
+repository_downloads_full_path = File.expand_path(repository_downloads_path, Settings.gitlab['user_home'])
+
+if repository_downloads_path.blank? || repositories_storages_path.any? { |path| [repository_downloads_path, repository_downloads_full_path].include?(path.gsub(/\/$/, '')) }
+ Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive')
+end
+
+#
# Backup
#
Settings['backup'] ||= Settingslogic.new({})
@@ -341,7 +380,6 @@ Settings.git['timeout'] ||= 10
Settings['satellites'] ||= Settingslogic.new({})
Settings.satellites['path'] = File.expand_path(Settings.satellites['path'] || "tmp/repo_satellites/", Rails.root)
-
#
# Extra customization
#
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index e026151a032..ed88c8ee1b8 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,6 +1,3 @@
-# GIT over HTTP
-require_dependency Rails.root.join('lib/gitlab/backend/grack_auth')
-
# GIT over SSH
require_dependency Rails.root.join('lib/gitlab/backend/shell')
diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb
new file mode 100644
index 00000000000..d92f64e1647
--- /dev/null
+++ b/config/initializers/6_validations.rb
@@ -0,0 +1,29 @@
+def storage_name_valid?(name)
+ !!(name =~ /\A[a-zA-Z0-9\-_]+\z/)
+end
+
+def find_parent_path(name, path)
+ parent = Pathname.new(path).realpath.parent
+ Gitlab.config.repositories.storages.detect do |n, p|
+ name != n && Pathname.new(p).realpath == parent
+ end
+end
+
+def storage_validation_error(message)
+ raise "#{message}. Please fix this in your gitlab.yml before starting GitLab."
+end
+
+def validate_storages
+ storage_validation_error('No repository storage path defined') if Gitlab.config.repositories.storages.empty?
+
+ Gitlab.config.repositories.storages.each do |name, path|
+ storage_validation_error("\"#{name}\" is not a valid storage name") unless storage_name_valid?(name)
+
+ parent_name, _parent_path = find_parent_path(name, path)
+ if parent_name
+ storage_validation_error("#{name} is a nested path of #{parent_name}. Nested paths are not supported for repository storages")
+ end
+ end
+end
+
+validate_storages unless Rails.env.test? || ENV['SKIP_STORAGE_VALIDATION'] == 'true'
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
new file mode 100644
index 00000000000..ae2ca258df1
--- /dev/null
+++ b/config/initializers/7_redis.rb
@@ -0,0 +1,3 @@
+# Make sure we initialize a Redis connection pool before Sidekiq starts
+# multi-threaded execution.
+Gitlab::Redis.with { nil }
diff --git a/config/initializers/ar5_batching.rb b/config/initializers/ar5_batching.rb
new file mode 100644
index 00000000000..35e8b3808e2
--- /dev/null
+++ b/config/initializers/ar5_batching.rb
@@ -0,0 +1,41 @@
+# Port ActiveRecord::Relation#in_batches from ActiveRecord 5.
+# https://github.com/rails/rails/blob/ac027338e4a165273607dccee49a3d38bc836794/activerecord/lib/active_record/relation/batches.rb#L184
+# TODO: this can be removed once we're using AR5.
+raise "Vendored ActiveRecord 5 code! Delete #{__FILE__}!" if ActiveRecord::VERSION::MAJOR >= 5
+
+module ActiveRecord
+ module Batches
+ # Differences from upstream: enumerator support was removed, and custom
+ # order/limit clauses are ignored without a warning.
+ def in_batches(of: 1000, start: nil, finish: nil, load: false)
+ raise "Must provide a block" unless block_given?
+
+ relation = self.reorder(batch_order).limit(of)
+ relation = relation.where(arel_table[primary_key].gteq(start)) if start
+ relation = relation.where(arel_table[primary_key].lteq(finish)) if finish
+ batch_relation = relation
+
+ loop do
+ if load
+ records = batch_relation.records
+ ids = records.map(&:id)
+ yielded_relation = self.where(primary_key => ids)
+ yielded_relation.load_records(records)
+ else
+ ids = batch_relation.pluck(primary_key)
+ yielded_relation = self.where(primary_key => ids)
+ end
+
+ break if ids.empty?
+
+ primary_key_offset = ids.last
+ raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset
+
+ yield yielded_relation
+
+ break if ids.length < of
+ batch_relation = relation.where(arel_table[primary_key].gt(primary_key_offset))
+ end
+ end
+ end
+end
diff --git a/config/initializers/ar_monkey_patch.rb b/config/initializers/ar_monkey_patch.rb
new file mode 100644
index 00000000000..0da584626ee
--- /dev/null
+++ b/config/initializers/ar_monkey_patch.rb
@@ -0,0 +1,57 @@
+# rubocop:disable Lint/RescueException
+
+# This patch fixes https://github.com/rails/rails/issues/26024
+# TODO: Remove it when it's no longer necessary
+
+module ActiveRecord
+ module Locking
+ module Optimistic
+ # We overwrite this method because we don't want to have default value
+ # for newly created records
+ def _create_record(attribute_names = self.attribute_names, *) # :nodoc:
+ super
+ end
+
+ def _update_record(attribute_names = self.attribute_names) #:nodoc:
+ return super unless locking_enabled?
+ return 0 if attribute_names.empty?
+
+ lock_col = self.class.locking_column
+
+ previous_lock_value = send(lock_col).to_i
+
+ # This line is added as a patch
+ previous_lock_value = nil if previous_lock_value == '0' || previous_lock_value == 0
+
+ increment_lock
+
+ attribute_names += [lock_col]
+ attribute_names.uniq!
+
+ begin
+ relation = self.class.unscoped
+
+ affected_rows = relation.where(
+ self.class.primary_key => id,
+ lock_col => previous_lock_value,
+ ).update_all(
+ attributes_for_update(attribute_names).map do |name|
+ [name, _read_attribute(name)]
+ end.to_h
+ )
+
+ unless affected_rows == 1
+ raise ActiveRecord::StaleObjectError.new(self, "update")
+ end
+
+ affected_rows
+
+ # If something went wrong, revert the version.
+ rescue Exception
+ send(lock_col + '=', previous_lock_value)
+ raise
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/ar_speed_up_migration_checking.rb b/config/initializers/ar_speed_up_migration_checking.rb
new file mode 100644
index 00000000000..1fe5defc01d
--- /dev/null
+++ b/config/initializers/ar_speed_up_migration_checking.rb
@@ -0,0 +1,18 @@
+if Rails.env.test?
+ require 'active_record/migration'
+
+ module ActiveRecord
+ class Migrator
+ class << self
+ alias_method :migrations_unmemoized, :migrations
+
+ # This method is called a large number of times per rspec example, and
+ # it reads + parses `db/migrate/*` each time. Memoizing it can save 0.5
+ # seconds per spec.
+ def migrations(paths)
+ @migrations ||= migrations_unmemoized(paths)
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/attr_encrypted_no_db_connection.rb b/config/initializers/attr_encrypted_no_db_connection.rb
index c668864089b..e007666b852 100644
--- a/config/initializers/attr_encrypted_no_db_connection.rb
+++ b/config/initializers/attr_encrypted_no_db_connection.rb
@@ -1,20 +1,21 @@
module AttrEncrypted
module Adapters
module ActiveRecord
- def attribute_instance_methods_as_symbols_with_no_db_connection
- # Use with_connection so the connection doesn't stay pinned to the thread.
- connected = ::ActiveRecord::Base.connection_pool.with_connection(&:active?) rescue false
-
- if connected
- # Call version from AttrEncrypted::Adapters::ActiveRecord
- attribute_instance_methods_as_symbols_without_no_db_connection
- else
- # Call version from AttrEncrypted, i.e., `super` with regards to AttrEncrypted::Adapters::ActiveRecord
- AttrEncrypted.instance_method(:attribute_instance_methods_as_symbols).bind(self).call
+ module DBConnectionQuerier
+ def attribute_instance_methods_as_symbols
+ # Use with_connection so the connection doesn't stay pinned to the thread.
+ connected = ::ActiveRecord::Base.connection_pool.with_connection(&:active?) rescue false
+
+ if connected
+ # Call version from AttrEncrypted::Adapters::ActiveRecord
+ super
+ else
+ # Call version from AttrEncrypted, i.e., `super` with regards to AttrEncrypted::Adapters::ActiveRecord
+ AttrEncrypted.instance_method(:attribute_instance_methods_as_symbols).bind(self).call
+ end
end
end
-
- alias_method_chain :attribute_instance_methods_as_symbols, :no_db_connection
+ prepend DBConnectionQuerier
end
end
end
diff --git a/config/initializers/connection_fix.rb b/config/initializers/connection_fix.rb
index d831a1838ed..d0b1444f607 100644
--- a/config/initializers/connection_fix.rb
+++ b/config/initializers/connection_fix.rb
@@ -20,7 +20,7 @@ if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
execute_without_retry(*args)
rescue ActiveRecord::StatementInvalid => e
if e.message =~ /server has gone away/i
- warn "Server timed out, retrying"
+ warn "Lost connection to MySQL server during query"
reconnect!
retry
else
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 021bdb11251..a8afc36fc78 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -100,6 +100,9 @@ Devise.setup do |config|
# secure: true in order to force SSL only cookies.
# config.cookie_options = {}
+ # Send a notification email when the user's password is changed
+ config.send_password_change_notification = true
+
# ==> Configuration for :validatable
# Range for password length. Default is 6..128.
config.password_length = 8..128
@@ -210,22 +213,9 @@ Devise.setup do |config|
end
if Gitlab::LDAP::Config.enabled?
- Gitlab.config.ldap.servers.values.each do |server|
- if server['allow_username_or_email_login']
- email_stripping_proc = ->(name) {name.gsub(/@.*\z/,'')}
- else
- email_stripping_proc = ->(name) {name}
- end
-
- config.omniauth server['provider_name'],
- host: server['host'],
- base: server['base'],
- uid: server['uid'],
- port: server['port'],
- method: server['method'],
- bind_dn: server['bind_dn'],
- password: server['password'],
- name_proc: email_stripping_proc
+ Gitlab::LDAP::Config.providers.each do |provider|
+ ldap_config = Gitlab::LDAP::Config.new(provider)
+ config.omniauth(provider, ldap_config.omniauth_options)
end
end
@@ -251,6 +241,10 @@ Devise.setup do |config|
end
end
+ if provider['name'] == 'shibboleth'
+ provider['args'][:fail_with_empty_uid] = true
+ end
+
# A Hash from the configuration will be passed as is.
provider_arguments << provider['args'].symbolize_keys
end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 618dba74151..fc4b0a72add 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -12,7 +12,8 @@ Doorkeeper.configure do
end
resource_owner_from_credentials do |routes|
- Gitlab::Auth.find_with_user_password(params[:username], params[:password])
+ user = Gitlab::Auth.find_with_user_password(params[:username], params[:password])
+ user unless user.try(:two_factor_enabled?)
end
# If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
diff --git a/config/initializers/gitlab_shell_secret_token.rb b/config/initializers/gitlab_shell_secret_token.rb
index 751fccead07..529dcdd4644 100644
--- a/config/initializers/gitlab_shell_secret_token.rb
+++ b/config/initializers/gitlab_shell_secret_token.rb
@@ -1,19 +1 @@
-# Be sure to restart your server when you modify this file.
-
-require 'securerandom'
-
-# Your secret key for verifying the gitlab_shell.
-
-
-secret_file = Gitlab.config.gitlab_shell.secret_file
-
-unless File.exist? secret_file
- # Generate a new token of 16 random hexadecimal characters and store it in secret_file.
- token = SecureRandom.hex(16)
- File.write(secret_file, token)
-end
-
-link_path = File.join(Gitlab.config.gitlab_shell.path, '.gitlab_shell_secret')
-if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(link_path)
- FileUtils.symlink(secret_file, link_path)
-end
+Gitlab::Shell.ensure_secret_token!
diff --git a/config/initializers/gitlab_workhorse_secret.rb b/config/initializers/gitlab_workhorse_secret.rb
new file mode 100644
index 00000000000..ed54dc11098
--- /dev/null
+++ b/config/initializers/gitlab_workhorse_secret.rb
@@ -0,0 +1,8 @@
+begin
+ Gitlab::Workhorse.secret
+rescue
+ Gitlab::Workhorse.write_secret
+end
+
+# Try a second time. If it does not work this will raise.
+Gitlab::Workhorse.secret
diff --git a/config/initializers/haml.rb b/config/initializers/haml.rb
deleted file mode 100644
index 1516476815a..00000000000
--- a/config/initializers/haml.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-Haml::Template.options[:ugly] = true
-
-# Remove the `:coffee` and `:coffeescript` filters
-#
-# See https://git.io/vztMu and http://stackoverflow.com/a/17571242/223897
-Haml::Filters.remove_filter('coffee')
-Haml::Filters.remove_filter('coffeescript')
diff --git a/config/initializers/hamlit.rb b/config/initializers/hamlit.rb
new file mode 100644
index 00000000000..7b545d8c06c
--- /dev/null
+++ b/config/initializers/hamlit.rb
@@ -0,0 +1,18 @@
+module Hamlit
+ class TemplateHandler
+ def call(template)
+ Engine.new(
+ generator: Temple::Generators::RailsOutputBuffer,
+ attr_quote: '"',
+ ).call(template.source)
+ end
+ end
+end
+
+ActionView::Template.register_template_handler(
+ :haml,
+ Hamlit::TemplateHandler.new,
+)
+
+Hamlit::Filters.remove_filter('coffee')
+Hamlit::Filters.remove_filter('coffeescript')
diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
index 79e2d23ab2e..4c91a61fb4a 100644
--- a/config/initializers/health_check.rb
+++ b/config/initializers/health_check.rb
@@ -1,3 +1,4 @@
HealthCheck.setup do |config|
config.standard_checks = ['database', 'migrations', 'cache']
+ config.full_checks = ['database', 'migrations', 'cache']
end
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
index d159f4eded2..3b8771543e4 100644
--- a/config/initializers/metrics.rb
+++ b/config/initializers/metrics.rb
@@ -67,8 +67,10 @@ if Gitlab::Metrics.enabled?
['app', 'finders'] => ['app', 'finders'],
['app', 'mailers', 'emails'] => ['app', 'mailers'],
['app', 'services', '**'] => ['app', 'services'],
+ ['lib', 'gitlab', 'conflicts'] => ['lib'],
['lib', 'gitlab', 'diff'] => ['lib'],
- ['lib', 'gitlab', 'email', 'message'] => ['lib']
+ ['lib', 'gitlab', 'email', 'message'] => ['lib'],
+ ['lib', 'gitlab', 'checks'] => ['lib']
}
paths_to_instrument.each do |(path, prefix)|
@@ -113,6 +115,10 @@ if Gitlab::Metrics.enabled?
config.instrument_methods(Banzai::Renderer)
config.instrument_methods(Banzai::Querying)
+ config.instrument_instance_methods(Banzai::ObjectRenderer)
+ config.instrument_instance_methods(Banzai::Redactor)
+ config.instrument_methods(Banzai::NoteRenderer)
+
[Issuable, Mentionable, Participable].each do |klass|
config.instrument_instance_methods(klass)
config.instrument_instance_methods(klass::ClassMethods)
@@ -128,6 +134,25 @@ if Gitlab::Metrics.enabled?
config.instrument_instance_methods(API::Helpers)
config.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
+
+ config.instrument_instance_methods(Rouge::Plugins::Redcarpet)
+ config.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
+
+ [:XML, :HTML].each do |namespace|
+ namespace_mod = Nokogiri.const_get(namespace)
+
+ config.instrument_methods(namespace_mod)
+ config.instrument_methods(namespace_mod::Document)
+ end
+
+ config.instrument_methods(Rinku)
+ config.instrument_instance_methods(Repository)
+
+ config.instrument_methods(Gitlab::Highlight)
+ config.instrument_instance_methods(Gitlab::Highlight)
+
+ # This is a Rails scope so we have to instrument it manually.
+ config.instrument_method(Project, :visible_to_user)
end
GC::Profiler.enable
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
index ca58ae92d1b..5e3e4c966cb 100644
--- a/config/initializers/mime_types.rb
+++ b/config/initializers/mime_types.rb
@@ -6,5 +6,12 @@
Mime::Type.register_alias "text/plain", :diff
Mime::Type.register_alias "text/plain", :patch
-Mime::Type.register_alias 'text/html', :markdown
-Mime::Type.register_alias 'text/html', :md
+Mime::Type.register_alias "text/html", :markdown
+Mime::Type.register_alias "text/html", :md
+
+Mime::Type.register "video/mp4", :mp4, [], [:m4v, :mov]
+Mime::Type.register "video/webm", :webm
+Mime::Type.register "video/ogg", :ogv
+
+Mime::Type.unregister :json
+Mime::Type.register 'application/json', :json, %w(application/vnd.git-lfs+json application/json)
diff --git a/config/initializers/postgresql_limit_fix.rb b/config/initializers/postgresql_limit_fix.rb
index 0cb3aaf4d24..4224d857e8a 100644
--- a/config/initializers/postgresql_limit_fix.rb
+++ b/config/initializers/postgresql_limit_fix.rb
@@ -1,5 +1,19 @@
if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
+ module LimitFilter
+ def add_column(table_name, column_name, type, options = {})
+ options.delete(:limit) if type == :text
+ super(table_name, column_name, type, options)
+ end
+
+ def change_column(table_name, column_name, type, options = {})
+ options.delete(:limit) if type == :text
+ super(table_name, column_name, type, options)
+ end
+ end
+
+ prepend ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::LimitFilter
+
class TableDefinition
def text(*args)
options = args.extract_options!
@@ -9,18 +23,5 @@ if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
column_names.each { |name| column(name, type, options) }
end
end
-
- def add_column_with_limit_filter(table_name, column_name, type, options = {})
- options.delete(:limit) if type == :text
- add_column_without_limit_filter(table_name, column_name, type, options)
- end
-
- def change_column_with_limit_filter(table_name, column_name, type, options = {})
- options.delete(:limit) if type == :text
- change_column_without_limit_filter(table_name, column_name, type, options)
- end
-
- alias_method_chain :add_column, :limit_filter
- alias_method_chain :change_column, :limit_filter
end
end
diff --git a/config/initializers/rack_attack.rb.example b/config/initializers/rack_attack.rb.example
index 30d05f16153..69052c029f2 100644
--- a/config/initializers/rack_attack.rb.example
+++ b/config/initializers/rack_attack.rb.example
@@ -10,7 +10,8 @@ paths_to_be_protected = [
"#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session",
"#{Rails.application.config.relative_url_root}/users",
"#{Rails.application.config.relative_url_root}/users/confirmation",
- "#{Rails.application.config.relative_url_root}/unsubscribes/"
+ "#{Rails.application.config.relative_url_root}/unsubscribes/",
+ "#{Rails.application.config.relative_url_root}/import/github/personal_access_token"
]
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
new file mode 100644
index 00000000000..8bb9ea29c33
--- /dev/null
+++ b/config/initializers/rack_attack_logging.rb
@@ -0,0 +1,7 @@
+# Adds logging for all Rack Attack blocks and throttling events.
+
+ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
+ if [:throttle, :blacklist].include? req.env['rack.attack.match_type']
+ Rails.logger.info("Rack_Attack: #{req.env['rack.attack.match_type']} #{req.ip} #{req.request_method} #{req.fullpath}")
+ end
+end
diff --git a/config/initializers/relative_naming_ci_namespace.rb b/config/initializers/relative_naming_ci_namespace.rb
new file mode 100644
index 00000000000..59abe1b9b91
--- /dev/null
+++ b/config/initializers/relative_naming_ci_namespace.rb
@@ -0,0 +1,16 @@
+# Description: https://coderwall.com/p/heed_q/rails-routing-and-namespaced-models
+#
+# This allows us to use CI ActiveRecord objects in all routes and use it:
+# - [project.namespace, project, build]
+#
+# instead of:
+# - namespace_project_build_path(project.namespace, project, build)
+#
+# Without that, Ci:: namespace is used for resolving routes:
+# - namespace_project_ci_build_path(project.namespace, project, build)
+
+module Ci
+ def self.use_relative_model_naming?
+ true
+ end
+end
diff --git a/config/initializers/request_profiler.rb b/config/initializers/request_profiler.rb
new file mode 100644
index 00000000000..a9aa802681a
--- /dev/null
+++ b/config/initializers/request_profiler.rb
@@ -0,0 +1,5 @@
+require 'gitlab/request_profiler/middleware'
+
+Rails.application.configure do |config|
+ config.middleware.use(Gitlab::RequestProfiler::Middleware)
+end
diff --git a/config/initializers/routing_draw.rb b/config/initializers/routing_draw.rb
new file mode 100644
index 00000000000..25003cf0239
--- /dev/null
+++ b/config/initializers/routing_draw.rb
@@ -0,0 +1,7 @@
+# Adds draw method into Rails routing
+# It allows us to keep routing splitted into files
+class ActionDispatch::Routing::Mapper
+ def draw(routes_name)
+ instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
+ end
+end
diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb
index dae3a4a9a93..291fa6c0abc 100644
--- a/config/initializers/secret_token.rb
+++ b/config/initializers/secret_token.rb
@@ -2,49 +2,86 @@
require 'securerandom'
-# Your secret key for verifying the integrity of signed cookies.
-# If you change this key, all old signed cookies will become invalid!
-# Make sure the secret is at least 30 characters and all random,
-# no regular words or you'll be exposed to dictionary attacks.
-
-def find_secure_token
- token_file = Rails.root.join('.secret')
- if ENV.key?('SECRET_KEY_BASE')
- ENV['SECRET_KEY_BASE']
- elsif File.exist? token_file
- # Use the existing token.
- File.read(token_file).chomp
- else
- # Generate a new token of 64 random hexadecimal characters and store it in token_file.
- token = SecureRandom.hex(64)
- File.write(token_file, token)
- token
+# Transition material in .secret to the secret_key_base key in config/secrets.yml.
+# Historically, ENV['SECRET_KEY_BASE'] takes precedence over .secret, so we maintain that
+# behavior.
+#
+# It also used to be the case that the key material in ENV['SECRET_KEY_BASE'] or .secret
+# was used to encrypt OTP (two-factor authentication) data so if present, we copy that key
+# material into config/secrets.yml under otp_key_base.
+#
+# Finally, if we have successfully migrated all secrets to config/secrets.yml, delete the
+# .secret file to avoid confusion.
+#
+def create_tokens
+ secret_file = Rails.root.join('.secret')
+ file_secret_key = File.read(secret_file).chomp if File.exist?(secret_file)
+ env_secret_key = ENV['SECRET_KEY_BASE']
+
+ # Ensure environment variable always overrides secrets.yml.
+ Rails.application.secrets.secret_key_base = env_secret_key if env_secret_key.present?
+
+ defaults = {
+ secret_key_base: file_secret_key || generate_new_secure_token,
+ otp_key_base: env_secret_key || file_secret_key || generate_new_secure_token,
+ db_key_base: generate_new_secure_token
+ }
+
+ missing_secrets = set_missing_keys(defaults)
+ write_secrets_yml(missing_secrets) unless missing_secrets.empty?
+
+ begin
+ File.delete(secret_file) if file_secret_key
+ rescue => e
+ warn "Error deleting useless .secret file: #{e}"
end
end
-Rails.application.config.secret_token = find_secure_token
-Rails.application.config.secret_key_base = find_secure_token
-
-# CI
def generate_new_secure_token
SecureRandom.hex(64)
end
-if Rails.application.secrets.db_key_base.blank?
- warn "Missing `db_key_base` for '#{Rails.env}' environment. The secrets will be generated and stored in `config/secrets.yml`"
+def warn_missing_secret(secret)
+ warn "Missing Rails.application.secrets.#{secret} for #{Rails.env} environment. The secret will be generated and stored in config/secrets.yml."
+end
- all_secrets = YAML.load_file('config/secrets.yml') if File.exist?('config/secrets.yml')
- all_secrets ||= {}
+def set_missing_keys(defaults)
+ defaults.stringify_keys.each_with_object({}) do |(key, default), missing|
+ if Rails.application.secrets[key].blank?
+ warn_missing_secret(key)
- # generate secrets
- env_secrets = all_secrets[Rails.env.to_s] || {}
- env_secrets['db_key_base'] ||= generate_new_secure_token
- all_secrets[Rails.env.to_s] = env_secrets
+ missing[key] = Rails.application.secrets[key] = default
+ end
+ end
+end
+
+def write_secrets_yml(missing_secrets)
+ secrets_yml = Rails.root.join('config/secrets.yml')
+ rails_env = Rails.env.to_s
+ secrets = YAML.load_file(secrets_yml) if File.exist?(secrets_yml)
+ secrets ||= {}
+ secrets[rails_env] ||= {}
+
+ secrets[rails_env].merge!(missing_secrets) do |key, old, new|
+ # Previously, it was possible this was set to the literal contents of an Erb
+ # expression that evaluated to an empty value. We don't want to support that
+ # specifically, just ensure we don't break things further.
+ #
+ if old.present?
+ warn <<EOM
+Rails.application.secrets.#{key} was blank, but the literal value in config/secrets.yml was:
+ #{old}
- # save secrets
- File.open('config/secrets.yml', 'w', 0600) do |file|
- file.write(YAML.dump(all_secrets))
+This probably isn't the expected value for this secret. To keep using a literal Erb string in config/secrets.yml, replace `<%` with `<%%`.
+EOM
+
+ exit 1 # rubocop:disable Rails/Exit
+ end
+
+ new
end
- Rails.application.secrets.db_key_base = env_secrets['db_key_base']
+ File.write(secrets_yml, YAML.dump(secrets), mode: 'w', perm: 0600)
end
+
+create_tokens
diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb
index 74fef7cadfe..4f30d1265c8 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -18,6 +18,9 @@ if Rails.env.production?
# Sanitize fields based on those sanitized from Rails.
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
+ # Sanitize authentication headers
+ config.sanitize_http_headers = %w[Authorization Private-Token]
+ config.tags = { program: Gitlab::Sentry.program_context }
end
end
end
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 0d9d87bac00..70be2617cab 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -13,9 +13,9 @@ end
if Rails.env.test?
Gitlab::Application.config.session_store :cookie_store, key: "_gitlab_session"
else
- redis_config = Gitlab::Redis.redis_store_options
+ redis_config = Gitlab::Redis.params
redis_config[:namespace] = Gitlab::Redis::SESSION_NAMESPACE
-
+
Gitlab::Application.config.session_store(
:redis_store, # Using the cookie_store would enable session replay attacks.
servers: redis_config,
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 7a2b9a7f6c1..b87b31d9697 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,21 +1,36 @@
+# Custom Redis configuration
+redis_config_hash = Gitlab::Redis.params
+redis_config_hash[:namespace] = Gitlab::Redis::SIDEKIQ_NAMESPACE
+
+# Default is to retry 25 times with exponential backoff. That's too much.
+Sidekiq.default_worker_options = { retry: 3 }
+
Sidekiq.configure_server do |config|
- config.redis = {
- url: Gitlab::Redis.url,
- namespace: Gitlab::Redis::SIDEKIQ_NAMESPACE
- }
+ config.redis = redis_config_hash
config.server_middleware do |chain|
chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS']
chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS']
+ chain.add Gitlab::SidekiqMiddleware::RequestStoreMiddleware unless ENV['SIDEKIQ_REQUEST_STORE'] == '0'
end
# Sidekiq-cron: load recurring jobs from gitlab.yml
# UGLY Hack to get nested hash from settingslogic
cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json)
# UGLY hack: Settingslogic doesn't allow 'class' key
- cron_jobs.each { |k,v| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') }
+ cron_jobs_required_keys = %w(job_class cron)
+ cron_jobs.each do |k, v|
+ if cron_jobs[k] && cron_jobs_required_keys.all? { |s| cron_jobs[k].key?(s) }
+ cron_jobs[k]['class'] = cron_jobs[k].delete('job_class')
+ else
+ cron_jobs.delete(k)
+ Rails.logger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
+ end
+ end
Sidekiq::Cron::Job.load_from_hash! cron_jobs
+ Gitlab::SidekiqThrottler.execute!
+
# Database pool should be at least `sidekiq_concurrency` + 2
# For more info, see: https://github.com/mperham/sidekiq/blob/master/4.0-Upgrade.md
config = ActiveRecord::Base.configurations[Rails.env] ||
@@ -30,8 +45,21 @@ Sidekiq.configure_server do |config|
end
Sidekiq.configure_client do |config|
- config.redis = {
- url: Gitlab::Redis.url,
- namespace: Gitlab::Redis::SIDEKIQ_NAMESPACE
- }
+ config.redis = redis_config_hash
+end
+
+# The Sidekiq client API always adds the queue to the Sidekiq queue
+# list, but mail_room and gitlab-shell do not. This is only necessary
+# for monitoring.
+config = YAML.load_file(Rails.root.join('config', 'sidekiq_queues.yml').to_s)
+
+begin
+ Sidekiq.redis do |conn|
+ conn.pipelined do
+ config[:queues].each do |queue|
+ conn.sadd('queues', queue[0])
+ end
+ end
+ end
+rescue Redis::BaseError, SocketError
end
diff --git a/config/initializers/smtp_settings.rb.sample b/config/initializers/smtp_settings.rb.sample
index 2287a76fca7..bd37080b1c8 100644
--- a/config/initializers/smtp_settings.rb.sample
+++ b/config/initializers/smtp_settings.rb.sample
@@ -10,6 +10,7 @@
if Rails.env.production?
Rails.application.config.action_mailer.delivery_method = :smtp
+ ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
address: "email.server.com",
port: 465,
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index d256a16d42b..cd869657c53 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -1,3 +1,24 @@
+# Override Rack::Request to make use of the same list of trusted_proxies
+# as the ActionDispatch::Request object. This is necessary for libraries
+# like rack_attack where they don't use ActionDispatch, and we want them
+# to block/throttle requests on private networks.
+# Rack Attack specific issue: https://github.com/kickstarter/rack-attack/issues/145
+module Rack
+ class Request
+ def trusted_proxy?(ip)
+ Rails.application.config.action_dispatch.trusted_proxies.any? { |proxy| proxy === ip }
+ rescue IPAddr::InvalidAddressError
+ false
+ end
+ end
+end
+
+gitlab_trusted_proxies = Array(Gitlab.config.gitlab.trusted_proxies).map do |proxy|
+ begin
+ IPAddr.new(proxy)
+ rescue IPAddr::InvalidAddressError
+ end
+end.compact
+
Rails.application.config.action_dispatch.trusted_proxies = (
- [ '127.0.0.1', '::1' ] + Array(Gitlab.config.gitlab.trusted_proxies)
-).map { |proxy| IPAddr.new(proxy) }
+ [ '127.0.0.1', '::1' ] + gitlab_trusted_proxies)
diff --git a/config/locales/en.yml b/config/locales/en.yml
index cedb5e207bd..12a59be79f0 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -5,6 +5,7 @@ en:
hello: "Hello world"
errors:
messages:
+ label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
wrong_size: "is the wrong size (should be %{file_size})"
size_too_small: "is too small (should be at least %{file_size})"
size_too_big: "is too big (should be at most %{file_size})"
diff --git a/config/mail_room.yml b/config/mail_room.yml
index 7cab24b295e..774c5350a45 100644
--- a/config/mail_room.yml
+++ b/config/mail_room.yml
@@ -1,47 +1,51 @@
+# If you change this file in a Merge Request, please also create
+# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+#
:mailboxes:
-<%
-require "yaml"
-require "json"
-require_relative "lib/gitlab/redis" unless defined?(Gitlab::Redis)
+ <%
+ require_relative "lib/gitlab/mail_room" unless defined?(Gitlab::MailRoom)
+ config = Gitlab::MailRoom.config
-rails_env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
-
-config_file = ENV["MAIL_ROOM_GITLAB_CONFIG_FILE"] || "config/gitlab.yml"
-if File.exists?(config_file)
- all_config = YAML.load_file(config_file)[rails_env]
-
- config = all_config["incoming_email"] || {}
- config['enabled'] = false if config['enabled'].nil?
- config['port'] = 143 if config['port'].nil?
- config['ssl'] = false if config['ssl'].nil?
- config['start_tls'] = false if config['start_tls'].nil?
- config['mailbox'] = "inbox" if config['mailbox'].nil?
-
- if config['enabled'] && config['address']
- redis_url = Gitlab::Redis.new(rails_env).url
- %>
+ if Gitlab::MailRoom.enabled?
+ %>
-
- :host: <%= config['host'].to_json %>
- :port: <%= config['port'].to_json %>
- :ssl: <%= config['ssl'].to_json %>
- :start_tls: <%= config['start_tls'].to_json %>
- :email: <%= config['user'].to_json %>
- :password: <%= config['password'].to_json %>
+ :host: <%= config[:host].to_json %>
+ :port: <%= config[:port].to_json %>
+ :ssl: <%= config[:ssl].to_json %>
+ :start_tls: <%= config[:start_tls].to_json %>
+ :email: <%= config[:user].to_json %>
+ :password: <%= config[:password].to_json %>
+ :idle_timeout: <%= config[:idle_timeout].to_json %>
- :name: <%= config['mailbox'].to_json %>
+ :name: <%= config[:mailbox].to_json %>
:delete_after_delivery: true
:delivery_method: sidekiq
:delivery_options:
- :redis_url: <%= redis_url.to_json %>
- :namespace: resque:gitlab
- :queue: incoming_email
+ :redis_url: <%= config[:redis_url].to_json %>
+ :namespace: <%= Gitlab::Redis::SIDEKIQ_NAMESPACE %>
+ :queue: email_receiver
:worker: EmailReceiverWorker
+ <% if config[:sentinels] %>
+ :sentinels:
+ <% config[:sentinels].each do |sentinel| %>
+ -
+ :host: <%= sentinel[:host] %>
+ :port: <%= sentinel[:port] %>
+ <% end %>
+ <% end %>
:arbitration_method: redis
:arbitration_options:
- :redis_url: <%= redis_url.to_json %>
- :namespace: mail_room:gitlab
+ :redis_url: <%= config[:redis_url].to_json %>
+ :namespace: <%= Gitlab::Redis::MAILROOM_NAMESPACE %>
+ <% if config[:sentinels] %>
+ :sentinels:
+ <% config[:sentinels].each do |sentinel| %>
+ -
+ :host: <%= sentinel[:host] %>
+ :port: <%= sentinel[:port] %>
+ <% end %>
+ <% end %>
<% end %>
-<% end %>
diff --git a/config/no_todos_messages.yml b/config/no_todos_messages.yml
new file mode 100644
index 00000000000..264a975b614
--- /dev/null
+++ b/config/no_todos_messages.yml
@@ -0,0 +1,11 @@
+# When the todo list on the user's dashboard becomes empty, a random message
+# from the list below will be shown.
+#
+# If you come up with a fun one, please feel free to contribute it to GitLab!
+# https://about.gitlab.com/contributing/
+---
+- Good job! Looks like you don't have any todos left.
+- Isn't an empty todo list beautiful?
+- Give yourself a pat on the back!
+- Nothing left to do, high five!
+- Henceforth you shall be known as "Todo Destroyer".
diff --git a/config/resque.yml.example b/config/resque.yml.example
index d98f43f71b2..0c19d8bc1d3 100644
--- a/config/resque.yml.example
+++ b/config/resque.yml.example
@@ -1,6 +1,34 @@
# If you change this file in a Merge Request, please also create
# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
#
-development: redis://localhost:6379
-test: redis://localhost:6379
-production: unix:/var/run/redis/redis.sock
+development:
+ url: redis://localhost:6379
+ # sentinels:
+ # -
+ # host: localhost
+ # port: 26380 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26381 # point to sentinel, not to redis port
+test:
+ url: redis://localhost:6379
+production:
+ # Redis (single instance)
+ url: unix:/var/run/redis/redis.sock
+ ##
+ # Redis + Sentinel (for HA)
+ #
+ # Please read instructions carefully before using it as you may lose data:
+ # http://redis.io/topics/sentinel
+ #
+ # You must specify a list of a few sentinels that will handle client connection
+ # please read here for more information: https://docs.gitlab.com/ce/administration/high_availability/redis.html
+ ##
+ # url: redis://master:6379
+ # sentinels:
+ # -
+ # host: slave1
+ # port: 26379 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26379 # point to sentinel, not to redis port
diff --git a/config/routes.rb b/config/routes.rb
index e45293cdf7f..7bf6c03e69b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,55 +3,19 @@ require 'sidekiq/cron/web'
require 'api/api'
Rails.application.routes.draw do
- if Gitlab::Sherlock.enabled?
- namespace :sherlock do
- resources :transactions, only: [:index, :show] do
- resources :queries, only: [:show]
- resources :file_samples, only: [:show]
-
- collection do
- delete :destroy_all
- end
- end
- end
- end
-
- if Rails.env.development?
- # Make the built-in Rails routes available in development, otherwise they'd
- # get swallowed by the `namespace/project` route matcher below.
- #
- # See https://git.io/va79N
- get '/rails/mailers' => 'rails/mailers#index'
- get '/rails/mailers/:path' => 'rails/mailers#preview'
- get '/rails/info/properties' => 'rails/info#properties'
- get '/rails/info/routes' => 'rails/info#routes'
- get '/rails/info' => 'rails/info#index'
-
- mount LetterOpenerWeb::Engine, at: '/rails/letter_opener'
- end
-
concern :access_requestable do
post :request_access, on: :collection
post :approve_access_request, on: :member
end
- namespace :ci do
- # CI API
- Ci::API::API.logger Rails.logger
- mount Ci::API::API => '/api'
-
- resource :lint, only: [:show, :create]
-
- resources :projects do
- member do
- get :status, to: 'projects#badge'
- get :integration
- end
- end
-
- root to: 'projects#index'
+ concern :awardable do
+ post :toggle_award_emoji, on: :member
end
+ draw :sherlock
+ draw :development
+ draw :ci
+
use_doorkeeper do
controllers applications: 'oauth/applications',
authorized_applications: 'oauth/authorized_applications',
@@ -73,43 +37,18 @@ Rails.application.routes.draw do
# JSON Web Token
get 'jwt/auth' => 'jwt#auth'
- # API
- API::API.logger Rails.logger
- mount API::API => '/api'
-
- constraint = lambda { |request| request.env['warden'].authenticate? and request.env['warden'].user.admin? }
- constraints constraint do
- mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
- end
-
# Health check
get 'health_check(/:checks)' => 'health_check#index', as: :health_check
- # Enable Grack support (for LFS only)
- mount Grack::AuthSpawner, at: '/', constraints: lambda { |request| /[-\/\w\.]+\.git\/(info\/lfs|gitlab-lfs)/.match(request.path_info) }, via: [:get, :post, :put]
+ # Koding route
+ get 'koding' => 'koding#index'
- # Help
- get 'help' => 'help#index'
- get 'help/:category/:file' => 'help#show', as: :help_page, constraints: { category: /.*/, file: /[^\/\.]+/ }
- get 'help/shortcuts'
- get 'help/ui' => 'help#ui'
+ draw :api
+ draw :sidekiq
+ draw :help
+ draw :snippets
- #
- # Global snippets
- #
- resources :snippets do
- member do
- get 'raw'
- end
- end
-
- get '/s/:username', to: redirect('/u/%{username}/snippets'),
- constraints: { username: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }
-
- #
# Invites
- #
-
resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
member do
post :accept
@@ -123,735 +62,26 @@ Rails.application.routes.draw do
end
end
- #
# Spam reports
- #
resources :abuse_reports, only: [:new, :create]
- #
# Notification settings
- #
resources :notification_settings, only: [:create, :update]
-
- #
- # Import
- #
- namespace :import do
- resource :github, only: [:create, :new], controller: :github do
- get :status
- get :callback
- get :jobs
- end
-
- resource :gitlab, only: [:create, :new], controller: :gitlab do
- get :status
- get :callback
- get :jobs
- end
-
- resource :bitbucket, only: [:create, :new], controller: :bitbucket do
- get :status
- get :callback
- get :jobs
- end
-
- resource :gitorious, only: [:create, :new], controller: :gitorious do
- get :status
- get :callback
- get :jobs
- end
-
- resource :google_code, only: [:create, :new], controller: :google_code do
- get :status
- post :callback
- get :jobs
-
- get :new_user_map, path: :user_map
- post :create_user_map, path: :user_map
- end
-
- resource :fogbugz, only: [:create, :new], controller: :fogbugz do
- get :status
- post :callback
- get :jobs
-
- get :new_user_map, path: :user_map
- post :create_user_map, path: :user_map
- end
-
- resource :gitlab_project, only: [:create, :new] do
- post :create
- end
- end
-
- #
- # Uploads
- #
-
- scope path: :uploads do
- # Note attachments and User/Group/Project avatars
- get ":model/:mounted_as/:id/:filename",
- to: "uploads#show",
- constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ }
-
- # Appearance
- get ":model/:mounted_as/:id/:filename",
- to: "uploads#show",
- constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ }
-
- # Project markdown uploads
- get ":namespace_id/:project_id/:secret/:filename",
- to: "projects/uploads#show",
- constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /[^\/]+/ }
- end
-
- # Redirect old note attachments path to new uploads path.
- get "files/note/:id/:filename",
- to: redirect("uploads/note/attachment/%{id}/%{filename}"),
- constraints: { filename: /[^\/]+/ }
-
- #
- # Explore area
- #
- namespace :explore do
- resources :projects, only: [:index] do
- collection do
- get :trending
- get :starred
- end
- end
-
- resources :groups, only: [:index]
- resources :snippets, only: [:index]
- root to: 'projects#trending'
- end
-
- # Compatibility with old routing
- get 'public' => 'explore/projects#index'
- get 'public/projects' => 'explore/projects#index'
-
- #
- # Admin Area
- #
- namespace :admin do
- resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
- resources :keys, only: [:show, :destroy]
- resources :identities, except: [:show]
-
- member do
- get :projects
- get :keys
- get :groups
- put :team_update
- put :block
- put :unblock
- put :unlock
- put :confirm
- post :impersonate
- patch :disable_two_factor
- delete 'remove/:email_id', action: 'remove_email', as: 'remove_email'
- end
- end
-
- resource :impersonation, only: :destroy
-
- resources :abuse_reports, only: [:index, :destroy]
- resources :spam_logs, only: [:index, :destroy]
-
- resources :applications
-
- resources :groups, constraints: { id: /[^\/]+/ } do
- member do
- put :members_update
- end
- end
-
- resources :deploy_keys, only: [:index, :new, :create, :destroy]
-
- resources :hooks, only: [:index, :create, :destroy] do
- get :test
- end
-
- resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do
- post :preview, on: :collection
- end
-
- resource :logs, only: [:show]
- resource :health_check, controller: 'health_check', only: [:show]
- resource :background_jobs, controller: 'background_jobs', only: [:show]
-
- resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
- root to: 'projects#index', as: :projects
-
- resources(:projects,
- path: '/',
- constraints: { id: /[a-zA-Z.0-9_\-]+/ },
- only: [:index, :show]) do
- root to: 'projects#show'
-
- member do
- put :transfer
- post :repository_check
- end
-
- resources :runner_projects, only: [:create, :destroy]
- end
- end
-
- resource :appearances, path: 'appearance' do
- member do
- get :preview
- delete :logo
- delete :header_logos
- end
- end
-
- resource :application_settings, only: [:show, :update] do
- resources :services
- put :reset_runners_token
- put :reset_health_check_token
- put :clear_repository_check_states
- end
-
- resources :labels
-
- resources :runners, only: [:index, :show, :update, :destroy] do
- member do
- get :resume
- get :pause
- end
- end
-
- resources :builds, only: :index do
- collection do
- post :cancel_all
- end
- end
-
- root to: 'dashboard#index'
- end
-
- #
- # Profile Area
- #
- resource :profile, only: [:show, :update] do
- member do
- get :audit_log
- get :applications, to: 'oauth/applications#index'
-
- put :reset_private_token
- put :update_username
- end
-
- scope module: :profiles do
- resource :account, only: [:show, :update] do
- member do
- delete :unlink
- end
- end
- resource :notifications, only: [:show, :update]
- resource :password, only: [:new, :create, :edit, :update] do
- member do
- put :reset
- end
- end
- resource :preferences, only: [:show, :update]
- resources :keys
- resources :emails, only: [:index, :create, :destroy]
- resource :avatar, only: [:destroy]
-
- resources :personal_access_tokens, only: [:index, :create] do
- member do
- put :revoke
- end
- end
-
- resource :two_factor_auth, only: [:show, :create, :destroy] do
- member do
- post :create_u2f
- post :codes
- patch :skip
- end
- end
- end
- end
-
- scope(path: 'u/:username',
- as: :user,
- constraints: { username: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ },
- controller: :users) do
- get :calendar
- get :calendar_activities
- get :groups
- get :projects
- get :contributed, as: :contributed_projects
- get :snippets
- get '/', action: :show
- end
-
- #
- # Dashboard Area
- #
- resource :dashboard, controller: 'dashboard', only: [] do
- get :issues
- get :merge_requests
- get :activity
-
- scope module: :dashboard do
- resources :milestones, only: [:index, :show]
- resources :labels, only: [:index]
-
- resources :groups, only: [:index]
- resources :snippets, only: [:index]
-
- resources :todos, only: [:index, :destroy] do
- collection do
- delete :destroy_all
- end
- end
-
- resources :projects, only: [:index] do
- collection do
- get :starred
- end
- end
- end
-
- root to: "dashboard/projects#index"
- end
-
- #
- # Groups Area
- #
- resources :groups, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do
- member do
- get :issues
- get :merge_requests
- get :projects
- get :activity
- end
-
- scope module: :groups do
- resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do
- post :resend_invite, on: :member
- delete :leave, on: :collection
- end
-
- resource :avatar, only: [:destroy]
- resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create]
- end
- end
-
- resources :projects, constraints: { id: /[^\/]+/ }, only: [:index, :new, :create]
-
- devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks,
- registrations: :registrations,
- passwords: :passwords,
- sessions: :sessions,
- confirmations: :confirmations }
-
- devise_scope :user do
- get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
- get '/users/almost_there' => 'confirmations#almost_there'
- end
-
- root to: "root#index"
-
- #
- # Project Area
- #
- resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
- resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except:
- [:new, :create, :index], path: "/") do
-
- member do
- put :transfer
- delete :remove_fork
- post :archive
- post :unarchive
- post :housekeeping
- post :toggle_star
- post :markdown_preview
- post :export
- post :remove_export
- post :generate_new_export
- get :download_export
- get :autocomplete_sources
- get :activity
- get :refs
- end
-
- scope module: :projects do
- # Git HTTP clients ('git clone' etc.)
- scope constraints: { id: /.+\.git/, format: nil } do
- get '/info/refs', to: 'git_http#info_refs'
- post '/git-upload-pack', to: 'git_http#git_upload_pack'
- post '/git-receive-pack', to: 'git_http#git_receive_pack'
- end
-
- # Allow /info/refs, /info/refs?service=git-upload-pack, and
- # /info/refs?service=git-receive-pack, but nothing else.
- #
- git_http_handshake = lambda do |request|
- request.query_string.blank? ||
- request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/)
- end
-
- ref_redirect = redirect do |params, request|
- path = "#{params[:namespace_id]}/#{params[:project_id]}.git/info/refs"
- path << "?#{request.query_string}" unless request.query_string.blank?
- path
- end
-
- get '/info/refs', constraints: git_http_handshake, to: ref_redirect
-
- # Blob routes:
- get '/new/*id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob'
- post '/create/*id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob'
- get '/edit/*id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob'
- put '/update/*id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob'
- post '/preview/*id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob'
-
- scope do
- get(
- '/blob/*id/diff',
- to: 'blob#diff',
- constraints: { id: /.+/, format: false },
- as: :blob_diff
- )
- get(
- '/blob/*id',
- to: 'blob#show',
- constraints: { id: /.+/, format: false },
- as: :blob
- )
- delete(
- '/blob/*id',
- to: 'blob#destroy',
- constraints: { id: /.+/, format: false }
- )
- put(
- '/blob/*id',
- to: 'blob#update',
- constraints: { id: /.+/, format: false }
- )
- post(
- '/blob/*id',
- to: 'blob#create',
- constraints: { id: /.+/, format: false }
- )
- end
-
- scope do
- get(
- '/raw/*id',
- to: 'raw#show',
- constraints: { id: /.+/, format: /(html|js)/ },
- as: :raw
- )
- end
-
- scope do
- get(
- '/tree/*id',
- to: 'tree#show',
- constraints: { id: /.+/, format: /(html|js)/ },
- as: :tree
- )
- end
-
- scope do
- get(
- '/find_file/*id',
- to: 'find_file#show',
- constraints: { id: /.+/, format: /html/ },
- as: :find_file
- )
- end
-
- scope do
- get(
- '/files/*id',
- to: 'find_file#list',
- constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ },
- as: :files
- )
- end
-
- scope do
- post(
- '/create_dir/*id',
- to: 'tree#create_dir',
- constraints: { id: /.+/ },
- as: 'create_dir'
- )
- end
-
- scope do
- get(
- '/blame/*id',
- to: 'blame#show',
- constraints: { id: /.+/, format: /(html|js)/ },
- as: :blame
- )
- end
-
- scope do
- get(
- '/commits/*id',
- to: 'commits#show',
- constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ },
- as: :commits
- )
- end
-
- resource :avatar, only: [:show, :destroy]
- resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
- member do
- get :branches
- get :builds
- post :cancel_builds
- post :retry_builds
- post :revert
- post :cherry_pick
- end
- end
-
- resources :compare, only: [:index, :create]
- resources :network, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ }
-
- resources :graphs, only: [:show], constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ } do
- member do
- get :commits
- get :ci
- get :languages
- end
- end
-
- get '/compare/:from...:to' => 'compare#show', :as => 'compare',
- :constraints => { from: /.+/, to: /.+/ }
-
- resources :snippets, constraints: { id: /\d+/ } do
- member do
- get 'raw'
- end
- end
-
- WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID
-
- scope do
- # Order matters to give priority to these matches
- get '/wikis/git_access', to: 'wikis#git_access'
- get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages'
- post '/wikis', to: 'wikis#create'
-
- get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID
- get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID
-
- get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID
- delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID
- put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID
- post '/wikis/*id/markdown_preview', to:'wikis#markdown_preview', constraints: WIKI_SLUG_ID, as: 'wiki_markdown_preview'
- end
-
- resource :repository, only: [:show, :create] do
- member do
- get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex }
- end
- end
-
- resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do
- member do
- get :test
- end
- end
-
- resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create] do
- member do
- put :enable
- put :disable
- end
- end
-
- resources :forks, only: [:index, :new, :create]
- resource :import, only: [:new, :create, :show]
-
- resources :refs, only: [] do
- collection do
- get 'switch'
- end
-
- member do
- # tree viewer logs
- get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
- # Directories with leading dots erroneously get rejected if git
- # ref regex used in constraints. Regex verification now done in controller.
- get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: {
- id: /.*/,
- path: /.*/
- }
- end
- end
-
- resources :merge_requests, constraints: { id: /\d+/ } do
- member do
- get :commits
- get :diffs
- get :builds
- get :merge_check
- post :merge
- post :cancel_merge_when_build_succeeds
- get :ci_status
- post :toggle_subscription
- post :toggle_award_emoji
- post :remove_wip
- end
-
- collection do
- get :branch_from
- get :branch_to
- get :update_branches
- end
- end
-
- resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
- resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do
- resource :release, only: [:edit, :update]
- end
-
- resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
- resources :variables, only: [:index, :show, :update, :create, :destroy]
- resources :triggers, only: [:index, :create, :destroy]
-
- resources :pipelines, only: [:index, :new, :create, :show] do
- member do
- post :cancel
- post :retry
- end
- end
-
- resources :environments, only: [:index, :show, :new, :create, :destroy]
-
- resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do
- collection do
- post :cancel_all
- end
-
- member do
- get :status
- post :cancel
- post :retry
- post :erase
- get :trace
- get :raw
- end
-
- resource :artifacts, only: [] do
- get :download
- get :browse, path: 'browse(/*path)', format: false
- get :file, path: 'file/*path', format: false
- post :keep
- end
- end
-
- resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
- member do
- get :test
- end
- end
-
- resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex }
-
- resources :milestones, constraints: { id: /\d+/ } do
- member do
- put :sort_issues
- put :sort_merge_requests
- end
- end
-
- resources :labels, constraints: { id: /\d+/ } do
- collection do
- post :generate
- post :set_priorities
- end
-
- member do
- post :toggle_subscription
- delete :remove_priority
- end
- end
-
- resources :issues, constraints: { id: /\d+/ } do
- member do
- post :toggle_subscription
- post :toggle_award_emoji
- get :referenced_merge_requests
- get :related_branches
- get :can_create_branch
- end
- collection do
- post :bulk_update
- end
- end
-
- resources :project_members, except: [:new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }, concerns: :access_requestable do
- collection do
- delete :leave
-
- # Used for import team
- # from another project
- get :import
- post :apply_import
- end
-
- member do
- post :resend_invite
- end
- end
-
- resources :group_links, only: [:index, :create, :destroy], constraints: { id: /\d+/ }
-
- resources :notes, only: [:index, :create, :destroy, :update], constraints: { id: /\d+/ } do
- member do
- post :toggle_award_emoji
- delete :delete_attachment
- end
- end
-
- resources :todos, only: [:create]
-
- resources :uploads, only: [:create] do
- collection do
- get ":secret/:filename", action: :show, as: :show, constraints: { filename: /[^\/]+/ }
- end
- end
-
- resources :runners, only: [:index, :edit, :update, :destroy, :show] do
- member do
- get :resume
- get :pause
- end
-
- collection do
- post :toggle_shared_runners
- end
- end
-
- resources :runner_projects, only: [:create, :destroy]
- resources :badges, only: [:index] do
- collection do
- scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do
- get :build, constraints: { format: /svg/ }
- end
- end
- end
- end
- end
- end
+ draw :import
+ draw :uploads
+ draw :explore
+ draw :admin
+ draw :profile
+ draw :dashboard
+ draw :group
+ draw :user
+ draw :project
# Get all keys of user
get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ }
- get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
+ root to: "root#index"
+
+ get '*unmatched_route', to: 'application#not_found'
end
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
new file mode 100644
index 00000000000..5ae985da561
--- /dev/null
+++ b/config/routes/admin.rb
@@ -0,0 +1,102 @@
+namespace :admin do
+ resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
+ resources :keys, only: [:show, :destroy]
+ resources :identities, except: [:show]
+
+ member do
+ get :projects
+ get :keys
+ get :groups
+ put :block
+ put :unblock
+ put :unlock
+ put :confirm
+ post :impersonate
+ patch :disable_two_factor
+ delete 'remove/:email_id', action: 'remove_email', as: 'remove_email'
+ end
+ end
+
+ resource :impersonation, only: :destroy
+
+ resources :abuse_reports, only: [:index, :destroy]
+ resources :spam_logs, only: [:index, :destroy] do
+ member do
+ post :mark_as_ham
+ end
+ end
+
+ resources :applications
+
+ resources :groups, constraints: { id: /[^\/]+/ } do
+ member do
+ put :members_update
+ end
+ end
+
+ resources :deploy_keys, only: [:index, :new, :create, :destroy]
+
+ resources :hooks, only: [:index, :create, :destroy] do
+ get :test
+ end
+
+ resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do
+ post :preview, on: :collection
+ end
+
+ resource :logs, only: [:show]
+ resource :health_check, controller: 'health_check', only: [:show]
+ resource :background_jobs, controller: 'background_jobs', only: [:show]
+ resource :system_info, controller: 'system_info', only: [:show]
+ resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ }
+
+ resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
+ root to: 'projects#index', as: :projects
+
+ resources(:projects,
+ path: '/',
+ constraints: { id: /[a-zA-Z.0-9_\-]+/ },
+ only: [:index, :show]) do
+ root to: 'projects#show'
+
+ member do
+ put :transfer
+ post :repository_check
+ end
+
+ resources :runner_projects, only: [:create, :destroy]
+ end
+ end
+
+ resource :appearances, only: [:show, :create, :update], path: 'appearance' do
+ member do
+ get :preview
+ delete :logo
+ delete :header_logos
+ end
+ end
+
+ resource :application_settings, only: [:show, :update] do
+ resources :services, only: [:index, :edit, :update]
+ put :reset_runners_token
+ put :reset_health_check_token
+ put :clear_repository_check_states
+ end
+
+ resources :labels
+
+ resources :runners, only: [:index, :show, :update, :destroy] do
+ member do
+ get :resume
+ get :pause
+ end
+ end
+
+ resources :builds, only: :index do
+ collection do
+ post :cancel_all
+ end
+ end
+
+ root to: 'dashboard#index'
+end
diff --git a/config/routes/api.rb b/config/routes/api.rb
new file mode 100644
index 00000000000..69c8efc151c
--- /dev/null
+++ b/config/routes/api.rb
@@ -0,0 +1,2 @@
+API::API.logger Rails.logger
+mount API::API => '/api'
diff --git a/config/routes/ci.rb b/config/routes/ci.rb
new file mode 100644
index 00000000000..47a049d5b20
--- /dev/null
+++ b/config/routes/ci.rb
@@ -0,0 +1,15 @@
+namespace :ci do
+ # CI API
+ Ci::API::API.logger Rails.logger
+ mount Ci::API::API => '/api'
+
+ resource :lint, only: [:show, :create]
+
+ resources :projects, only: [:index, :show] do
+ member do
+ get :status, to: 'projects#badge'
+ end
+ end
+
+ root to: 'projects#index'
+end
diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb
new file mode 100644
index 00000000000..fb20c63bc63
--- /dev/null
+++ b/config/routes/dashboard.rb
@@ -0,0 +1,27 @@
+resource :dashboard, controller: 'dashboard', only: [] do
+ get :issues
+ get :merge_requests
+ get :activity
+
+ scope module: :dashboard do
+ resources :milestones, only: [:index, :show]
+ resources :labels, only: [:index]
+
+ resources :groups, only: [:index]
+ resources :snippets, only: [:index]
+
+ resources :todos, only: [:index, :destroy] do
+ collection do
+ delete :destroy_all
+ end
+ end
+
+ resources :projects, only: [:index] do
+ collection do
+ get :starred
+ end
+ end
+ end
+
+ root to: "dashboard/projects#index"
+end
diff --git a/config/routes/development.rb b/config/routes/development.rb
new file mode 100644
index 00000000000..9b2b47c6a21
--- /dev/null
+++ b/config/routes/development.rb
@@ -0,0 +1,13 @@
+if Rails.env.development?
+ # Make the built-in Rails routes available in development, otherwise they'd
+ # get swallowed by the `namespace/project` route matcher below.
+ #
+ # See https://git.io/va79N
+ get '/rails/mailers' => 'rails/mailers#index'
+ get '/rails/mailers/:path' => 'rails/mailers#preview'
+ get '/rails/info/properties' => 'rails/info#properties'
+ get '/rails/info/routes' => 'rails/info#routes'
+ get '/rails/info' => 'rails/info#index'
+
+ mount LetterOpenerWeb::Engine, at: '/rails/letter_opener'
+end
diff --git a/config/routes/explore.rb b/config/routes/explore.rb
new file mode 100644
index 00000000000..42ec5e8abec
--- /dev/null
+++ b/config/routes/explore.rb
@@ -0,0 +1,16 @@
+namespace :explore do
+ resources :projects, only: [:index] do
+ collection do
+ get :trending
+ get :starred
+ end
+ end
+
+ resources :groups, only: [:index]
+ resources :snippets, only: [:index]
+ root to: 'projects#trending'
+end
+
+# Compatibility with old routing
+get 'public' => 'explore/projects#index'
+get 'public/projects' => 'explore/projects#index'
diff --git a/config/routes/git_http.rb b/config/routes/git_http.rb
new file mode 100644
index 00000000000..03adc4815f3
--- /dev/null
+++ b/config/routes/git_http.rb
@@ -0,0 +1,37 @@
+scope constraints: { id: /.+\.git/, format: nil } do
+ # Git HTTP clients ('git clone' etc.)
+ get '/info/refs', to: 'git_http#info_refs'
+ post '/git-upload-pack', to: 'git_http#git_upload_pack'
+ post '/git-receive-pack', to: 'git_http#git_receive_pack'
+
+ # Git LFS API (metadata)
+ post '/info/lfs/objects/batch', to: 'lfs_api#batch'
+ post '/info/lfs/objects', to: 'lfs_api#deprecated'
+ get '/info/lfs/objects/*oid', to: 'lfs_api#deprecated'
+
+ # GitLab LFS object storage
+ scope constraints: { oid: /[a-f0-9]{64}/ } do
+ get '/gitlab-lfs/objects/*oid', to: 'lfs_storage#download'
+
+ scope constraints: { size: /[0-9]+/ } do
+ put '/gitlab-lfs/objects/*oid/*size/authorize', to: 'lfs_storage#upload_authorize'
+ put '/gitlab-lfs/objects/*oid/*size', to: 'lfs_storage#upload_finalize'
+ end
+ end
+end
+
+# Allow /info/refs, /info/refs?service=git-upload-pack, and
+# /info/refs?service=git-receive-pack, but nothing else.
+#
+git_http_handshake = lambda do |request|
+ request.query_string.blank? ||
+ request.query_string.match(/\Aservice=git-(upload|receive)-pack\z/)
+end
+
+ref_redirect = redirect do |params, request|
+ path = "#{params[:namespace_id]}/#{params[:project_id]}.git/info/refs"
+ path << "?#{request.query_string}" unless request.query_string.blank?
+ path
+end
+
+get '/info/refs', constraints: git_http_handshake, to: ref_redirect
diff --git a/config/routes/group.rb b/config/routes/group.rb
new file mode 100644
index 00000000000..a3a001178b4
--- /dev/null
+++ b/config/routes/group.rb
@@ -0,0 +1,45 @@
+require 'constraints/group_url_constrainer'
+
+constraints(GroupUrlConstrainer.new) do
+ scope(path: ':id',
+ as: :group,
+ constraints: { id: Gitlab::Regex.namespace_route_regex },
+ controller: :groups) do
+ get '/', action: :show
+ patch '/', action: :update
+ put '/', action: :update
+ delete '/', action: :destroy
+ end
+end
+
+resources :groups, only: [:index, :new, :create]
+
+scope(path: 'groups/:id',
+ controller: :groups,
+ constraints: { id: Gitlab::Regex.namespace_route_regex }) do
+ get :edit, as: :edit_group
+ get :issues, as: :issues_group
+ get :merge_requests, as: :merge_requests_group
+ get :projects, as: :projects_group
+ get :activity, as: :activity_group
+end
+
+scope(path: 'groups/:group_id',
+ module: :groups,
+ as: :group,
+ constraints: { group_id: Gitlab::Regex.namespace_route_regex }) do
+ resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do
+ post :resend_invite, on: :member
+ delete :leave, on: :collection
+ end
+
+ resource :avatar, only: [:destroy]
+ resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create]
+
+ resources :labels, except: [:show], constraints: { id: /\d+/ } do
+ post :toggle_subscription, on: :member
+ end
+end
+
+# Must be last route in this file
+get 'groups/:id' => 'groups#show', as: :group_canonical, constraints: { id: Gitlab::Regex.namespace_route_regex }
diff --git a/config/routes/help.rb b/config/routes/help.rb
new file mode 100644
index 00000000000..d53822da9ec
--- /dev/null
+++ b/config/routes/help.rb
@@ -0,0 +1,4 @@
+get 'help' => 'help#index'
+get 'help/shortcuts' => 'help#shortcuts'
+get 'help/ui' => 'help#ui'
+get 'help/*path' => 'help#show', as: :help_page
diff --git a/config/routes/import.rb b/config/routes/import.rb
new file mode 100644
index 00000000000..89f3b3f6378
--- /dev/null
+++ b/config/routes/import.rb
@@ -0,0 +1,42 @@
+namespace :import do
+ resource :github, only: [:create, :new], controller: :github do
+ post :personal_access_token
+ get :status
+ get :callback
+ get :jobs
+ end
+
+ resource :gitlab, only: [:create], controller: :gitlab do
+ get :status
+ get :callback
+ get :jobs
+ end
+
+ resource :bitbucket, only: [:create], controller: :bitbucket do
+ get :status
+ get :callback
+ get :jobs
+ end
+
+ resource :google_code, only: [:create, :new], controller: :google_code do
+ get :status
+ post :callback
+ get :jobs
+
+ get :new_user_map, path: :user_map
+ post :create_user_map, path: :user_map
+ end
+
+ resource :fogbugz, only: [:create, :new], controller: :fogbugz do
+ get :status
+ post :callback
+ get :jobs
+
+ get :new_user_map, path: :user_map
+ post :create_user_map, path: :user_map
+ end
+
+ resource :gitlab_project, only: [:create, :new] do
+ post :create
+ end
+end
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
new file mode 100644
index 00000000000..6b91485da9e
--- /dev/null
+++ b/config/routes/profile.rb
@@ -0,0 +1,50 @@
+resource :profile, only: [:show, :update] do
+ member do
+ get :audit_log
+ get :applications, to: 'oauth/applications#index'
+
+ put :reset_private_token
+ put :reset_incoming_email_token
+ put :update_username
+ end
+
+ scope module: :profiles do
+ resource :account, only: [:show] do
+ member do
+ delete :unlink
+ end
+ end
+ resource :notifications, only: [:show, :update]
+ resource :password, only: [:new, :create, :edit, :update] do
+ member do
+ put :reset
+ end
+ end
+ resource :preferences, only: [:show, :update]
+ resources :keys, only: [:index, :show, :new, :create, :destroy]
+ resources :emails, only: [:index, :create, :destroy]
+ resources :chat_names, only: [:index, :new, :create, :destroy] do
+ collection do
+ delete :deny
+ end
+ end
+
+ resource :avatar, only: [:destroy]
+
+ resources :personal_access_tokens, only: [:index, :create] do
+ member do
+ put :revoke
+ end
+ end
+
+ resource :two_factor_auth, only: [:show, :create, :destroy] do
+ member do
+ post :create_u2f
+ post :codes
+ patch :skip
+ end
+ end
+
+ resources :u2f_registrations, only: [:destroy]
+ end
+end
diff --git a/config/routes/project.rb b/config/routes/project.rb
new file mode 100644
index 00000000000..d6eae1c9fce
--- /dev/null
+++ b/config/routes/project.rb
@@ -0,0 +1,315 @@
+resources :projects, constraints: { id: /[^\/]+/ }, only: [:index, :new, :create]
+
+resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
+ resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except:
+ [:new, :create, :index], path: "/") do
+ member do
+ put :transfer
+ delete :remove_fork
+ post :archive
+ post :unarchive
+ post :housekeeping
+ post :toggle_star
+ post :preview_markdown
+ post :export
+ post :remove_export
+ post :generate_new_export
+ get :download_export
+ get :autocomplete_sources
+ get :activity
+ get :refs
+ put :new_issue_address
+ end
+
+ scope module: :projects do
+ draw :git_http
+
+ #
+ # Templates
+ #
+ get '/templates/:template_type/:key' => 'templates#show', as: :template
+
+ resource :avatar, only: [:show, :destroy]
+ resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do
+ member do
+ get :branches
+ get :builds
+ get :pipelines
+ post :cancel_builds
+ post :retry_builds
+ post :revert
+ post :cherry_pick
+ get :diff_for_path
+ end
+ end
+
+ resources :compare, only: [:index, :create] do
+ collection do
+ get :diff_for_path
+ end
+ end
+
+ get '/compare/:from...:to', to: 'compare#show', as: 'compare', constraints: { from: /.+/, to: /.+/ }
+
+ # Don't use format parameter as file extension (old 3.0.x behavior)
+ # See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
+ scope format: false do
+ resources :network, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex }
+
+ resources :graphs, only: [:show], constraints: { id: Gitlab::Regex.git_reference_regex } do
+ member do
+ get :commits
+ get :ci
+ get :languages
+ end
+ end
+ end
+
+ resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do
+ member do
+ get 'raw'
+ end
+ end
+
+ resources :services, constraints: { id: /[^\/]+/ }, only: [:index, :edit, :update] do
+ member do
+ get :test
+ end
+ end
+
+ resources :deploy_keys, constraints: { id: /\d+/ }, only: [:index, :new, :create] do
+ member do
+ put :enable
+ put :disable
+ end
+ end
+
+ resources :forks, only: [:index, :new, :create]
+ resource :import, only: [:new, :create, :show]
+
+ resources :merge_requests, concerns: :awardable, constraints: { id: /\d+/ } do
+ member do
+ get :commits
+ get :diffs
+ get :conflicts
+ get :conflict_for_path
+ get :builds
+ get :pipelines
+ get :merge_check
+ post :merge
+ post :cancel_merge_when_build_succeeds
+ get :ci_status
+ get :ci_environments_status
+ post :toggle_subscription
+ post :remove_wip
+ get :diff_for_path
+ post :resolve_conflicts
+ post :assign_related_issues
+ end
+
+ collection do
+ get :branch_from
+ get :branch_to
+ get :update_branches
+ get :diff_for_path
+ post :bulk_update
+ get :new_diffs, path: 'new/diffs'
+ end
+
+ resources :discussions, only: [], constraints: { id: /\h{40}/ } do
+ member do
+ post :resolve
+ delete :resolve, action: :unresolve
+ end
+ end
+ end
+
+ resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+ delete :merged_branches, controller: 'branches', action: :destroy_all_merged
+ resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do
+ resource :release, only: [:edit, :update]
+ end
+
+ resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
+ resources :variables, only: [:index, :show, :update, :create, :destroy]
+ resources :triggers, only: [:index, :create, :destroy]
+
+ resources :pipelines, only: [:index, :new, :create, :show] do
+ collection do
+ resource :pipelines_settings, path: 'settings', only: [:show, :update]
+ end
+
+ member do
+ post :cancel
+ post :retry
+ end
+ end
+
+ resources :environments, except: [:destroy] do
+ member do
+ post :stop
+ end
+ end
+
+ resource :cycle_analytics, only: [:show]
+
+ namespace :cycle_analytics do
+ scope :events, controller: 'events' do
+ get :issue
+ get :plan
+ get :code
+ get :test
+ get :review
+ get :staging
+ get :production
+ end
+ end
+
+ resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do
+ collection do
+ post :cancel_all
+
+ resources :artifacts, only: [] do
+ collection do
+ get :latest_succeeded,
+ path: '*ref_name_and_path',
+ format: false
+ end
+ end
+ end
+
+ member do
+ get :status
+ post :cancel
+ post :retry
+ post :play
+ post :erase
+ get :trace
+ get :raw
+ end
+
+ resource :artifacts, only: [] do
+ get :download
+ get :browse, path: 'browse(/*path)', format: false
+ get :file, path: 'file/*path', format: false
+ post :keep
+ end
+ end
+
+ resources :hooks, only: [:index, :create, :destroy], constraints: { id: /\d+/ } do
+ member do
+ get :test
+ end
+ end
+
+ resources :container_registry, only: [:index, :destroy], constraints: { id: Gitlab::Regex.container_registry_reference_regex }
+
+ resources :milestones, constraints: { id: /\d+/ } do
+ member do
+ put :sort_issues
+ put :sort_merge_requests
+ end
+ end
+
+ resources :labels, except: [:show], constraints: { id: /\d+/ } do
+ collection do
+ post :generate
+ post :set_priorities
+ end
+
+ member do
+ post :toggle_subscription
+ delete :remove_priority
+ end
+ end
+
+ resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do
+ member do
+ post :toggle_subscription
+ post :mark_as_spam
+ get :referenced_merge_requests
+ get :related_branches
+ get :can_create_branch
+ end
+ collection do
+ post :bulk_update
+ end
+ end
+
+ resources :project_members, except: [:show, :new, :edit], constraints: { id: /[a-zA-Z.\/0-9_\-#%+]+/ }, concerns: :access_requestable do
+ collection do
+ delete :leave
+
+ # Used for import team
+ # from another project
+ get :import
+ post :apply_import
+ end
+
+ member do
+ post :resend_invite
+ end
+ end
+
+ resources :group_links, only: [:index, :create, :update, :destroy], constraints: { id: /\d+/ }
+
+ resources :notes, only: [:index, :create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do
+ member do
+ delete :delete_attachment
+ post :resolve
+ delete :resolve, action: :unresolve
+ end
+ end
+
+ resources :boards, only: [:index, :show] do
+ scope module: :boards do
+ resources :issues, only: [:update]
+
+ resources :lists, only: [:index, :create, :update, :destroy] do
+ collection do
+ post :generate
+ end
+
+ resources :issues, only: [:index, :create]
+ end
+ end
+ end
+
+ resources :todos, only: [:create]
+
+ resources :uploads, only: [:create] do
+ collection do
+ get ":secret/:filename", action: :show, as: :show, constraints: { filename: /[^\/]+/ }
+ end
+ end
+
+ resources :runners, only: [:index, :edit, :update, :destroy, :show] do
+ member do
+ get :resume
+ get :pause
+ end
+
+ collection do
+ post :toggle_shared_runners
+ end
+ end
+
+ resources :runner_projects, only: [:create, :destroy]
+ resources :badges, only: [:index] do
+ collection do
+ scope '*ref', constraints: { ref: Gitlab::Regex.git_reference_regex } do
+ constraints format: /svg/ do
+ get :build
+ get :coverage
+ end
+ end
+ end
+ end
+
+ # Since both wiki and repository routing contains wildcard characters
+ # its preferable to keep it below all other project routes
+ draw :wiki
+ draw :repository
+ end
+ end
+end
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
new file mode 100644
index 00000000000..76dcf113aea
--- /dev/null
+++ b/config/routes/repository.rb
@@ -0,0 +1,110 @@
+# All routing related to repositoty browsing
+
+resource :repository, only: [:create] do
+ member do
+ get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex }
+ end
+end
+
+resources :refs, only: [] do
+ collection do
+ get 'switch'
+ end
+
+ member do
+ # tree viewer logs
+ get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
+ # Directories with leading dots erroneously get rejected if git
+ # ref regex used in constraints. Regex verification now done in controller.
+ get 'logs_tree/*path' => 'refs#logs_tree', as: :logs_file, constraints: {
+ id: /.*/,
+ path: /.*/
+ }
+ end
+end
+
+get '/new/*id', to: 'blob#new', constraints: { id: /.+/ }, as: 'new_blob'
+post '/create/*id', to: 'blob#create', constraints: { id: /.+/ }, as: 'create_blob'
+get '/edit/*id', to: 'blob#edit', constraints: { id: /.+/ }, as: 'edit_blob'
+put '/update/*id', to: 'blob#update', constraints: { id: /.+/ }, as: 'update_blob'
+post '/preview/*id', to: 'blob#preview', constraints: { id: /.+/ }, as: 'preview_blob'
+
+scope do
+ get(
+ '/blob/*id/diff',
+ to: 'blob#diff',
+ constraints: { id: /.+/, format: false },
+ as: :blob_diff
+ )
+ get(
+ '/blob/*id',
+ to: 'blob#show',
+ constraints: { id: /.+/, format: false },
+ as: :blob
+ )
+ delete(
+ '/blob/*id',
+ to: 'blob#destroy',
+ constraints: { id: /.+/, format: false }
+ )
+ put(
+ '/blob/*id',
+ to: 'blob#update',
+ constraints: { id: /.+/, format: false }
+ )
+ post(
+ '/blob/*id',
+ to: 'blob#create',
+ constraints: { id: /.+/, format: false }
+ )
+
+ get(
+ '/raw/*id',
+ to: 'raw#show',
+ constraints: { id: /.+/, format: /(html|js)/ },
+ as: :raw
+ )
+
+ get(
+ '/tree/*id',
+ to: 'tree#show',
+ constraints: { id: /.+/, format: /(html|js)/ },
+ as: :tree
+ )
+
+ get(
+ '/find_file/*id',
+ to: 'find_file#show',
+ constraints: { id: /.+/, format: /html/ },
+ as: :find_file
+ )
+
+ get(
+ '/files/*id',
+ to: 'find_file#list',
+ constraints: { id: /(?:[^.]|\.(?!json$))+/, format: /json/ },
+ as: :files
+ )
+
+ post(
+ '/create_dir/*id',
+ to: 'tree#create_dir',
+ constraints: { id: /.+/ },
+ as: 'create_dir'
+ )
+
+ get(
+ '/blame/*id',
+ to: 'blame#show',
+ constraints: { id: /.+/, format: /(html|js)/ },
+ as: :blame
+ )
+
+ # File/dir history
+ get(
+ '/commits/*id',
+ to: 'commits#show',
+ constraints: { id: /.+/, format: false },
+ as: :commits
+ )
+end
diff --git a/config/routes/sherlock.rb b/config/routes/sherlock.rb
new file mode 100644
index 00000000000..c9969f91c36
--- /dev/null
+++ b/config/routes/sherlock.rb
@@ -0,0 +1,12 @@
+if Gitlab::Sherlock.enabled?
+ namespace :sherlock do
+ resources :transactions, only: [:index, :show] do
+ resources :queries, only: [:show]
+ resources :file_samples, only: [:show]
+
+ collection do
+ delete :destroy_all
+ end
+ end
+ end
+end
diff --git a/config/routes/sidekiq.rb b/config/routes/sidekiq.rb
new file mode 100644
index 00000000000..d3e6bc4c292
--- /dev/null
+++ b/config/routes/sidekiq.rb
@@ -0,0 +1,4 @@
+constraint = lambda { |request| request.env['warden'].authenticate? and request.env['warden'].user.admin? }
+constraints constraint do
+ mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
+end
diff --git a/config/routes/snippets.rb b/config/routes/snippets.rb
new file mode 100644
index 00000000000..3ca096f31ba
--- /dev/null
+++ b/config/routes/snippets.rb
@@ -0,0 +1,9 @@
+resources :snippets, concerns: :awardable do
+ member do
+ get 'raw'
+ get 'download'
+ end
+end
+
+get '/s/:username', to: redirect('/u/%{username}/snippets'),
+ constraints: { username: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }
diff --git a/config/routes/uploads.rb b/config/routes/uploads.rb
new file mode 100644
index 00000000000..2b22148a134
--- /dev/null
+++ b/config/routes/uploads.rb
@@ -0,0 +1,21 @@
+scope path: :uploads do
+ # Note attachments and User/Group/Project avatars
+ get ":model/:mounted_as/:id/:filename",
+ to: "uploads#show",
+ constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ }
+
+ # Appearance
+ get ":model/:mounted_as/:id/:filename",
+ to: "uploads#show",
+ constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ }
+
+ # Project markdown uploads
+ get ":namespace_id/:project_id/:secret/:filename",
+ to: "projects/uploads#show",
+ constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: /[^\/]+/ }
+end
+
+# Redirect old note attachments path to new uploads path.
+get "files/note/:id/:filename",
+ to: redirect("uploads/note/attachment/%{id}/%{filename}"),
+ constraints: { filename: /[^\/]+/ }
diff --git a/config/routes/user.rb b/config/routes/user.rb
new file mode 100644
index 00000000000..dc1068af6f6
--- /dev/null
+++ b/config/routes/user.rb
@@ -0,0 +1,45 @@
+require 'constraints/user_url_constrainer'
+
+devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks,
+ registrations: :registrations,
+ passwords: :passwords,
+ sessions: :sessions,
+ confirmations: :confirmations }
+
+devise_scope :user do
+ get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
+ get '/users/almost_there' => 'confirmations#almost_there'
+end
+
+constraints(UserUrlConstrainer.new) do
+ scope(path: ':username',
+ as: :user,
+ constraints: { username: Gitlab::Regex.namespace_route_regex },
+ controller: :users) do
+ get '/', action: :show
+ end
+end
+
+scope(constraints: { username: Gitlab::Regex.namespace_route_regex }) do
+ scope(path: 'users/:username',
+ as: :user,
+ controller: :users) do
+ get :calendar
+ get :calendar_activities
+ get :groups
+ get :projects
+ get :contributed, as: :contributed_projects
+ get :snippets
+ get :exists
+ get '/', to: redirect('/%{username}')
+ end
+
+ # Compatibility with old routing
+ # TODO (dzaporozhets): remove in 10.0
+ get '/u/:username', to: redirect('/%{username}')
+ # TODO (dzaporozhets): remove in 9.0
+ get '/u/:username/groups', to: redirect('/users/%{username}/groups')
+ get '/u/:username/projects', to: redirect('/users/%{username}/projects')
+ get '/u/:username/snippets', to: redirect('/users/%{username}/snippets')
+ get '/u/:username/contributed', to: redirect('/users/%{username}/contributed')
+end
diff --git a/config/routes/wiki.rb b/config/routes/wiki.rb
new file mode 100644
index 00000000000..ecd4d395d66
--- /dev/null
+++ b/config/routes/wiki.rb
@@ -0,0 +1,16 @@
+WIKI_SLUG_ID = { id: /\S+/ } unless defined? WIKI_SLUG_ID
+
+scope do
+ # Order matters to give priority to these matches
+ get '/wikis/git_access', to: 'wikis#git_access'
+ get '/wikis/pages', to: 'wikis#pages', as: 'wiki_pages'
+ post '/wikis', to: 'wikis#create'
+
+ get '/wikis/*id/history', to: 'wikis#history', as: 'wiki_history', constraints: WIKI_SLUG_ID
+ get '/wikis/*id/edit', to: 'wikis#edit', as: 'wiki_edit', constraints: WIKI_SLUG_ID
+
+ get '/wikis/*id', to: 'wikis#show', as: 'wiki', constraints: WIKI_SLUG_ID
+ delete '/wikis/*id', to: 'wikis#destroy', constraints: WIKI_SLUG_ID
+ put '/wikis/*id', to: 'wikis#update', constraints: WIKI_SLUG_ID
+ post '/wikis/*id/preview_markdown', to: 'wikis#preview_markdown', constraints: WIKI_SLUG_ID, as: 'wiki_preview_markdown'
+end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
new file mode 100644
index 00000000000..69136b73946
--- /dev/null
+++ b/config/sidekiq_queues.yml
@@ -0,0 +1,50 @@
+# This configuration file should be exclusively used to set queue settings for
+# Sidekiq. Any other setting should be specified using the Sidekiq CLI or the
+# Sidekiq Ruby API (see config/initializers/sidekiq.rb).
+---
+# All the queues to process and their weights. Every queue _must_ have a weight
+# defined.
+#
+# The available weights are as follows
+#
+# 1: low priority
+# 2: medium priority
+# 3: high priority
+# 5: _super_ high priority, this should only be used for _very_ important queues
+#
+# As per http://stackoverflow.com/a/21241357/290102 the formula for calculating
+# the likelihood of a job being popped off a queue (given all queues have work
+# to perform) is:
+#
+# chance = (queue weight / total weight of all queues) * 100
+:queues:
+ - [post_receive, 5]
+ - [merge, 5]
+ - [update_merge_requests, 3]
+ - [process_commit, 2]
+ - [new_note, 2]
+ - [build, 2]
+ - [pipeline, 2]
+ - [gitlab_shell, 2]
+ - [email_receiver, 2]
+ - [emails_on_push, 2]
+ - [mailers, 2]
+ - [repository_fork, 1]
+ - [repository_import, 1]
+ - [project_service, 1]
+ - [clear_database_cache, 1]
+ - [delete_user, 1]
+ - [delete_merged_branches, 1]
+ - [authorized_projects, 1]
+ - [expire_build_instance_artifacts, 1]
+ - [group_destroy, 1]
+ - [irker, 1]
+ - [project_cache, 1]
+ - [project_destroy, 1]
+ - [project_export, 1]
+ - [project_web_hook, 1]
+ - [repository_check, 1]
+ - [system_hook, 1]
+ - [git_garbage_collect, 1]
+ - [cronjob, 1]
+ - [default, 1]
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index e5058cebce8..40a16a32359 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -44,7 +44,7 @@ listen "127.0.0.1:8080", :tcp_nopush => true
# nuke workers after 30 seconds instead of 60 seconds (the default)
#
# NOTICE: git push over http depends on this value.
-# If you want be able to push huge amount of data to git repository over http
+# If you want to be able to push huge amount of data to git repository over http
# you will have to increase this value too.
#
# Example of output if you try to push 1GB repo to GitLab over http.
@@ -82,7 +82,7 @@ GC.respond_to?(:copy_on_write_friendly=) and
check_client_connection false
before_fork do |server, worker|
- # the following is highly recomended for Rails + "preload_app true"
+ # the following is highly recommended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!