diff options
author | Rob Watson <rob@mixlr.com> | 2018-01-03 11:07:03 +0300 |
---|---|---|
committer | Rob Watson <rob@mixlr.com> | 2018-03-22 21:58:36 +0300 |
commit | 9d45951fcaeda4f01a2e4be2480d980a3e7cd37e (patch) | |
tree | 536b456729edad79ba718d987a39f235587d4dfb /app | |
parent | 53d352aaf4ce7f0d2bcaf04cce5252b753ef7938 (diff) |
Add HTTPS-only pages
Closes #28857
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects/pages_controller.rb | 22 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 18 | ||||
-rw-r--r-- | app/models/pages_domain.rb | 10 | ||||
-rw-r--r-- | app/models/project.rb | 21 | ||||
-rw-r--r-- | app/services/projects/update_pages_configuration_service.rb | 6 | ||||
-rw-r--r-- | app/services/projects/update_service.rb | 10 | ||||
-rw-r--r-- | app/validators/certificate_validator.rb | 2 | ||||
-rw-r--r-- | app/views/projects/pages/_https_only.html.haml | 10 | ||||
-rw-r--r-- | app/views/projects/pages/show.html.haml | 3 |
9 files changed, 96 insertions, 6 deletions
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb index d421b1a8eb5..cae6e2c40b8 100644 --- a/app/controllers/projects/pages_controller.rb +++ b/app/controllers/projects/pages_controller.rb @@ -21,4 +21,26 @@ class Projects::PagesController < Projects::ApplicationController end end end + + def update + result = Projects::UpdateService.new(@project, current_user, project_params).execute + + respond_to do |format| + format.html do + if result[:status] == :success + flash[:notice] = 'Your changes have been saved' + else + flash[:alert] = 'Something went wrong on our end' + end + + redirect_to project_pages_path(@project) + end + end + end + + private + + def project_params + params.require(:project).permit(:pages_https_only) + end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index da9fe734f1c..15f48e43a28 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -531,4 +531,22 @@ module ProjectsHelper def can_show_last_commit_in_list?(project) can?(current_user, :read_cross_project) && project.commit end + + def pages_https_only_disabled? + !@project.pages_domains.all?(&:https?) + end + + def pages_https_only_title + return unless pages_https_only_disabled? + + "You must enable HTTPS for all your domains first" + end + + def pages_https_only_label_class + if pages_https_only_disabled? + "list-label disabled" + else + "list-label" + end + end end diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb index 588bd50ed77..2e478a24778 100644 --- a/app/models/pages_domain.rb +++ b/app/models/pages_domain.rb @@ -6,8 +6,10 @@ class PagesDomain < ActiveRecord::Base validates :domain, hostname: { allow_numeric_hostname: true } validates :domain, uniqueness: { case_sensitive: false } - validates :certificate, certificate: true, allow_nil: true, allow_blank: true - validates :key, certificate_key: true, allow_nil: true, allow_blank: true + validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? } + validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? } + validates :key, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? } + validates :key, certificate_key: true, if: ->(domain) { domain.key.present? } validates :verification_code, presence: true, allow_blank: false validate :validate_pages_domain @@ -46,6 +48,10 @@ class PagesDomain < ActiveRecord::Base !Gitlab::CurrentSettings.pages_domain_verification_enabled? || enabled_until.present? end + def https? + certificate.present? + end + def to_param domain end diff --git a/app/models/project.rb b/app/models/project.rb index 250680e2a2c..48a81ddb82e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -267,6 +267,7 @@ class Project < ActiveRecord::Base validate :visibility_level_allowed_by_group validate :visibility_level_allowed_as_fork validate :check_wiki_path_conflict + validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) } validates :repository_storage, presence: true, inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } } @@ -737,6 +738,26 @@ class Project < ActiveRecord::Base end end + def pages_https_only + return false unless Gitlab.config.pages.external_https + + super + end + + def pages_https_only? + return false unless Gitlab.config.pages.external_https + + super + end + + def validate_pages_https_only + return unless pages_https_only? + + unless pages_domains.all?(&:https?) + errors.add(:pages_https_only, "cannot be enabled unless all domains have TLS certificates") + end + end + def to_param if persisted? && errors.include?(:path) path_was diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb index 52ff64cc938..25017c5cbe3 100644 --- a/app/services/projects/update_pages_configuration_service.rb +++ b/app/services/projects/update_pages_configuration_service.rb @@ -18,7 +18,8 @@ module Projects def pages_config { - domains: pages_domains_config + domains: pages_domains_config, + https_only: project.pages_https_only? } end @@ -27,7 +28,8 @@ module Projects { domain: domain.domain, certificate: domain.certificate, - key: domain.key + key: domain.key, + https_only: project.pages_https_only? && domain.https? } end end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 5f2615a2c01..679f4a9cb62 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -24,6 +24,8 @@ module Projects system_hook_service.execute_hooks_for(project, :update) end + update_pages_config if changing_pages_https_only? + success else model_errors = project.errors.full_messages.to_sentence @@ -67,5 +69,13 @@ module Projects log_error("Could not create wiki for #{project.full_name}") Gitlab::Metrics.counter(:wiki_can_not_be_created_total, 'Counts the times we failed to create a wiki') end + + def update_pages_config + Projects::UpdatePagesConfigurationService.new(project).execute + end + + def changing_pages_https_only? + project.previous_changes.include?(:pages_https_only) + end end end diff --git a/app/validators/certificate_validator.rb b/app/validators/certificate_validator.rb index 5239e70a326..b0c9a1b92a4 100644 --- a/app/validators/certificate_validator.rb +++ b/app/validators/certificate_validator.rb @@ -16,8 +16,6 @@ class CertificateValidator < ActiveModel::EachValidator private def valid_certificate_pem?(value) - return false unless value - OpenSSL::X509::Certificate.new(value).present? rescue OpenSSL::X509::CertificateError false diff --git a/app/views/projects/pages/_https_only.html.haml b/app/views/projects/pages/_https_only.html.haml new file mode 100644 index 00000000000..6a3ffce949f --- /dev/null +++ b/app/views/projects/pages/_https_only.html.haml @@ -0,0 +1,10 @@ += form_for @project, url: namespace_project_pages_path(@project.namespace.becomes(Namespace), @project), html: { class: 'inline', title: pages_https_only_title } do |f| + = f.check_box :pages_https_only, class: 'pull-left', disabled: pages_https_only_disabled? + + .prepend-left-20 + = f.label :pages_https_only, class: pages_https_only_label_class do + %strong Force domains with SSL certificates to use HTTPS + + - unless pages_https_only_disabled? + .prepend-top-10 + = f.submit 'Save', class: 'btn btn-success' diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml index 04e647c0dc6..f17d9d24db6 100644 --- a/app/views/projects/pages/show.html.haml +++ b/app/views/projects/pages/show.html.haml @@ -13,6 +13,9 @@ Combined with the power of GitLab CI and the help of GitLab Runner you can deploy static pages for your individual projects, your user or your group. +- if Gitlab.config.pages.external_https + = render 'https_only' + %hr.clearfix = render 'access' |