Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock4
-rw-r--r--app/controllers/projects/pages_controller.rb94
-rw-r--r--app/controllers/projects_controller.rb10
-rw-r--r--app/helpers/projects_helper.rb8
-rw-r--r--app/models/project.rb51
-rw-r--r--app/policies/project_policy.rb1
-rw-r--r--app/services/projects/update_pages_configuration_service.rb53
-rw-r--r--app/validators/certificate_key_validator.rb24
-rw-r--r--app/validators/certificate_validator.rb30
-rw-r--r--app/views/layouts/nav/_project_settings.html.haml4
-rw-r--r--app/views/projects/pages/_access.html.haml34
-rw-r--r--app/views/projects/pages/_destroy.haml10
-rw-r--r--app/views/projects/pages/_disabled.html.haml4
-rw-r--r--app/views/projects/pages/_form.html.haml35
-rw-r--r--app/views/projects/pages/_remove_certificate.html.haml16
-rw-r--r--app/views/projects/pages/_upload_certificate.html.haml32
-rw-r--r--app/views/projects/pages/_use.html.haml18
-rw-r--r--app/views/projects/pages/show.html.haml18
-rw-r--r--app/workers/pages_worker.rb6
-rw-r--r--config/initializers/1_settings.rb1
-rw-r--r--config/routes/project.rb5
-rw-r--r--db/migrate/20160209125808_add_pages_custom_domain_to_projects.rb10
23 files changed, 451 insertions, 20 deletions
diff --git a/Gemfile b/Gemfile
index dd7c93c5a75..bc1b13c7331 100644
--- a/Gemfile
+++ b/Gemfile
@@ -48,6 +48,9 @@ gem 'rqrcode-rails3', '~> 0.1.7'
gem 'attr_encrypted', '~> 3.0.0'
gem 'u2f', '~> 0.2.1'
+# GitLab Pages
+gem 'validates_hostname', '~> 1.0.0'
+
# Browser detection
gem 'browser', '~> 2.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index 3b207d19d1f..6263b02b041 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -799,6 +799,9 @@ GEM
get_process_mem (~> 0)
unicorn (>= 4, < 6)
uniform_notifier (1.10.0)
+ validates_hostname (1.0.5)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
version_sorter (2.1.0)
virtus (1.0.5)
axiom-types (~> 0.1)
@@ -1014,6 +1017,7 @@ DEPENDENCIES
unf (~> 0.1.4)
unicorn (~> 5.1.0)
unicorn-worker-killer (~> 0.4.4)
+ validates_hostname (~> 1.0.0)
version_sorter (~> 2.1.0)
virtus (~> 1.0.1)
vmstat (~> 2.3.0)
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
new file mode 100644
index 00000000000..ef0ed505142
--- /dev/null
+++ b/app/controllers/projects/pages_controller.rb
@@ -0,0 +1,94 @@
+class Projects::PagesController < Projects::ApplicationController
+ layout 'project_settings'
+
+ before_action :authorize_update_pages!, except: [:show]
+ before_action :authorize_remove_pages!, only: :destroy
+
+ helper_method :valid_certificate?, :valid_certificate_key?
+ helper_method :valid_key_for_certificiate?, :valid_certificate_intermediates?
+ helper_method :certificate, :certificate_key
+
+ def show
+ end
+
+ def update
+ if @project.update_attributes(pages_params)
+ redirect_to namespace_project_pages_path(@project.namespace, @project)
+ else
+ render 'show'
+ end
+ end
+
+ def certificate
+ @project.remove_pages_certificate
+ end
+
+ def destroy
+ @project.remove_pages
+
+ respond_to do |format|
+ format.html { redirect_to project_path(@project) }
+ end
+ end
+
+ private
+
+ def pages_params
+ params.require(:project).permit(
+ :pages_custom_certificate,
+ :pages_custom_certificate_key,
+ :pages_custom_domain,
+ :pages_redirect_http,
+ )
+ end
+
+ def valid_certificate?
+ certificate.present?
+ end
+
+ def valid_certificate_key?
+ certificate_key.present?
+ end
+
+ def valid_key_for_certificiate?
+ return false unless certificate
+ return false unless certificate_key
+
+ certificate.verify(certificate_key)
+ rescue OpenSSL::X509::CertificateError
+ false
+ end
+
+ def valid_certificate_intermediates?
+ return false unless certificate
+
+ store = OpenSSL::X509::Store.new
+ store.set_default_paths
+
+ # This forces to load all intermediate certificates stored in `pages_custom_certificate`
+ Tempfile.open('project_certificate') do |f|
+ f.write(@project.pages_custom_certificate)
+ f.flush
+ store.add_file(f.path)
+ end
+
+ store.verify(certificate)
+ rescue OpenSSL::X509::StoreError
+ false
+ end
+
+ def certificate
+ return unless @project.pages_custom_certificate
+
+ @certificate ||= OpenSSL::X509::Certificate.new(@project.pages_custom_certificate)
+ rescue OpenSSL::X509::CertificateError
+ nil
+ end
+
+ def certificate_key
+ return unless @project.pages_custom_certificate_key
+ @certificate_key ||= OpenSSL::PKey::RSA.new(@project.pages_custom_certificate_key)
+ rescue OpenSSL::PKey::PKeyError
+ nil
+ end
+end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 123dc179e73..444ff837bb3 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -151,16 +151,6 @@ class ProjectsController < Projects::ApplicationController
end
end
- def remove_pages
- return access_denied! unless can?(current_user, :remove_pages, @project)
-
- @project.remove_pages
-
- respond_to do |format|
- format.html { redirect_to project_path(@project) }
- end
- end
-
def housekeeping
::Projects::HousekeepingService.new(@project).execute
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index eb98204285d..63aa182502d 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -81,6 +81,14 @@ module ProjectsHelper
"You are going to remove the fork relationship to source project #{@project.forked_from_project.name_with_namespace}. Are you ABSOLUTELY sure?"
end
+ def remove_pages_message(project)
+ "You are going to remove the pages for #{project.name_with_namespace}.\n Are you ABSOLUTELY sure?"
+ end
+
+ def remove_pages_certificate_message(project)
+ "You are going to remove a certificates for #{project.name_with_namespace}.\n Are you ABSOLUTELY sure?"
+ end
+
def project_nav_tabs
@nav_tabs ||= get_project_nav_tabs(@project, current_user)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 8a8aca44945..34618817fb6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -76,6 +76,8 @@ class Project < ActiveRecord::Base
attr_accessor :new_default_branch
attr_accessor :old_path_with_namespace
+ attr_encrypted :pages_custom_certificate_key, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
+
alias_attribute :title, :name
# Relations
@@ -205,6 +207,11 @@ class Project < ActiveRecord::Base
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
+ validates :pages_custom_domain, hostname: true, allow_blank: true, allow_nil: true
+ validates_uniqueness_of :pages_custom_domain, allow_nil: true, allow_blank: true
+ validates :pages_custom_certificate, certificate: { intermediate: true }
+ validates :pages_custom_certificate_key, certificate_key: true
+
add_authentication_token_field :runners_token
before_save :ensure_runners_token
@@ -1164,16 +1171,27 @@ class Project < ActiveRecord::Base
end
def pages_url
- if Dir.exist?(public_pages_path)
- host = "#{namespace.path}.#{Settings.pages.host}"
- url = Gitlab.config.pages.url.sub(/^https?:\/\//) do |prefix|
- "#{prefix}#{namespace.path}."
- end
+ return unless Dir.exist?(public_pages_path)
+
+ host = "#{namespace.path}.#{Settings.pages.host}"
+ url = Gitlab.config.pages.url.sub(/^https?:\/\//) do |prefix|
+ "#{prefix}#{namespace.path}."
+ end
+
+ # If the project path is the same as host, leave the short version
+ return url if host == path
+
+ "#{url}/#{path}"
+ end
- # If the project path is the same as host, leave the short version
- return url if host == path
+ def pages_custom_url
+ return unless pages_custom_domain
+ return unless Dir.exist?(public_pages_path)
- "#{url}/#{path}"
+ if Gitlab.config.pages.https
+ return "https://#{pages_custom_domain}"
+ else
+ return "http://#{pages_custom_domain}"
end
end
@@ -1185,6 +1203,15 @@ class Project < ActiveRecord::Base
File.join(pages_path, 'public')
end
+ def remove_pages_certificate
+ update(
+ pages_custom_certificate: nil,
+ pages_custom_certificate_key: nil
+ )
+
+ UpdatePagesConfigurationService.new(self).execute
+ end
+
def remove_pages
# 1. We rename pages to temporary directory
# 2. We wait 5 minutes, due to NFS caching
@@ -1194,6 +1221,14 @@ class Project < ActiveRecord::Base
if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.path)
PagesWorker.perform_in(5.minutes, :remove, namespace.path, temp_path)
end
+
+ update(
+ pages_custom_certificate: nil,
+ pages_custom_certificate_key: nil,
+ pages_custom_domain: nil
+ )
+
+ UpdatePagesConfigurationService.new(self).execute
end
def wiki
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 63bc639688d..ca5b39a001f 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -110,6 +110,7 @@ class ProjectPolicy < BasePolicy
can! :admin_pipeline
can! :admin_environment
can! :admin_deployment
+ can! :update_pages
end
def public_access!
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
new file mode 100644
index 00000000000..be4c2fbef8c
--- /dev/null
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -0,0 +1,53 @@
+module Projects
+ class UpdatePagesConfigurationService < BaseService
+ attr_reader :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ update_file(pages_cname_file, project.pages_custom_domain)
+ update_file(pages_certificate_file, project.pages_custom_certificate)
+ update_file(pages_certificate_file_key, project.pages_custom_certificate_key)
+ reload_daemon
+ success
+ rescue => e
+ error(e.message)
+ end
+
+ private
+
+ def reload_daemon
+ # GitLab Pages daemon constantly watches for modification time of `pages.path`
+ # It reloads configuration when `pages.path` is modified
+ File.touch(Settings.pages.path)
+ end
+
+ def pages_path
+ @pages_path ||= project.pages_path
+ end
+
+ def pages_cname_file
+ File.join(pages_path, 'CNAME')
+ end
+
+ def pages_certificate_file
+ File.join(pages_path, 'domain.crt')
+ end
+
+ def pages_certificate_key_file
+ File.join(pages_path, 'domain.key')
+ end
+
+ def update_file(file, data)
+ if data
+ File.open(file, 'w') do |file|
+ file.write(data)
+ end
+ else
+ File.rm_r(file)
+ end
+ end
+ end
+end
diff --git a/app/validators/certificate_key_validator.rb b/app/validators/certificate_key_validator.rb
new file mode 100644
index 00000000000..3b5bd30db1a
--- /dev/null
+++ b/app/validators/certificate_key_validator.rb
@@ -0,0 +1,24 @@
+# UrlValidator
+#
+# Custom validator for private keys.
+#
+# class Project < ActiveRecord::Base
+# validates :certificate_key, certificate_key: true
+# end
+#
+class CertificateKeyValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless valid_private_key_pem?(value)
+ record.errors.add(attribute, "must be a valid PEM private key")
+ end
+ end
+
+ private
+
+ def valid_private_key_pem?(value)
+ pkey = OpenSSL::PKey::RSA.new(value)
+ pkey.private?
+ rescue OpenSSL::PKey::PKeyError
+ false
+ end
+end
diff --git a/app/validators/certificate_validator.rb b/app/validators/certificate_validator.rb
new file mode 100644
index 00000000000..2cba5a435b7
--- /dev/null
+++ b/app/validators/certificate_validator.rb
@@ -0,0 +1,30 @@
+# UrlValidator
+#
+# Custom validator for private keys.
+#
+# class Project < ActiveRecord::Base
+# validates :certificate_key, certificate_key: true
+# end
+#
+class CertificateValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ certificate = parse_certificate(value)
+ unless certificate
+ record.errors.add(attribute, "must be a valid PEM certificate")
+ end
+
+ if options[:intermediates]
+ unless certificate
+ record.errors.add(attribute, "certificate verification failed: missing intermediate certificates")
+ end
+ end
+ end
+
+ private
+
+ def parse_certificate(value)
+ OpenSSL::X509::Certificate.new(value)
+ rescue OpenSSL::X509::CertificateError
+ nil
+ end
+end
diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml
index c6df66d2c3c..d6c158b6de3 100644
--- a/app/views/layouts/nav/_project_settings.html.haml
+++ b/app/views/layouts/nav/_project_settings.html.haml
@@ -34,3 +34,7 @@
= link_to namespace_project_pipelines_settings_path(@project.namespace, @project), title: 'CI/CD Pipelines' do
%span
CI/CD Pipelines
+ = nav_link(controller: :pages) do
+ = link_to namespace_project_pages_path(@project.namespace, @project), title: 'Pages', data: {placement: 'right'} do
+ %span
+ Pages
diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml
new file mode 100644
index 00000000000..d64f99fd22b
--- /dev/null
+++ b/app/views/projects/pages/_access.html.haml
@@ -0,0 +1,34 @@
+- if @project.pages_url
+ .panel.panel-default
+ .panel-heading
+ Access pages
+ .panel-body
+ %p
+ %strong
+ Congratulations! Your pages are served at:
+ %p= link_to @project.pages_url, @project.pages_url
+
+ - if Settings.pages.custom_domain && @project.pages_custom_url
+ %p= link_to @project.pages_custom_url, @project.pages_custom_url
+
+ - if @project.pages_custom_certificate
+ - unless valid_certificate?
+ #error_explanation
+ .alert.alert-warning
+ Your certificate is invalid.
+
+ - unless valid_certificate_key?
+ #error_explanation
+ .alert.alert-warning
+ Your private key is invalid.
+
+ - unless valid_key_for_certificiate?
+ #error_explanation
+ .alert.alert-warning
+ Your private key can't be used with your certificate.
+
+ - unless valid_certificate_intermediates?
+ #error_explanation
+ .alert.alert-warning
+ Your certificate doesn't have intermediates.
+ Your page may not work properly.
diff --git a/app/views/projects/pages/_destroy.haml b/app/views/projects/pages/_destroy.haml
new file mode 100644
index 00000000000..61b995a5934
--- /dev/null
+++ b/app/views/projects/pages/_destroy.haml
@@ -0,0 +1,10 @@
+- if can?(current_user, :remove_pages, @project) && @project.pages_url
+ .panel.panel-default.panel.panel-danger
+ .panel-heading Remove pages
+ .errors-holder
+ .panel-body
+ = form_tag(namespace_project_pages_path(@project.namespace, @project), method: :delete, class: 'form-horizontal') do
+ %p
+ Removing the pages will prevent from exposing them to outside world.
+ .form-actions
+ = button_to 'Remove pages', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_pages_message(@project) }
diff --git a/app/views/projects/pages/_disabled.html.haml b/app/views/projects/pages/_disabled.html.haml
new file mode 100644
index 00000000000..cf9ef5b4d6f
--- /dev/null
+++ b/app/views/projects/pages/_disabled.html.haml
@@ -0,0 +1,4 @@
+.panel.panel-default
+ .nothing-here-block
+ GitLab Pages is disabled.
+ Ask your system's administrator to enable it.
diff --git a/app/views/projects/pages/_form.html.haml b/app/views/projects/pages/_form.html.haml
new file mode 100644
index 00000000000..a7b03d552db
--- /dev/null
+++ b/app/views/projects/pages/_form.html.haml
@@ -0,0 +1,35 @@
+- if can?(current_user, :update_pages, @project)
+ .panel.panel-default
+ .panel-heading
+ Settings
+ .panel-body
+ = form_for [@project], url: namespace_project_pages_path(@project.namespace, @project), html: { class: 'form-horizontal fieldset-form' } do |f|
+ - if @project.errors.any?
+ #error_explanation
+ .alert.alert-danger
+ - @project.errors.full_messages.each do |msg|
+ %p= msg
+
+ .form-group
+ = f.label :pages_domain, class: 'control-label' do
+ Custom domain
+ .col-sm-10
+ - if Settings.pages.custom_domain
+ = f.text_field :pages_custom_domain, required: false, autocomplete: 'off', class: 'form-control'
+ %span.help-inline Allows you to serve the pages under your domain
+ - else
+ .nothing-here-block
+ Support for custom domains and certificates is disabled.
+ Ask your system's administrator to enable it.
+
+ - if Settings.pages.https
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :pages_redirect_http do
+ = f.check_box :pages_redirect_http
+ %span.descr Force HTTPS
+ .help-block Redirect the HTTP to HTTPS forcing to always use the secure connection
+
+ .form-actions
+ = f.submit 'Save changes', class: "btn btn-save"
diff --git a/app/views/projects/pages/_remove_certificate.html.haml b/app/views/projects/pages/_remove_certificate.html.haml
new file mode 100644
index 00000000000..e8c0d03adfa
--- /dev/null
+++ b/app/views/projects/pages/_remove_certificate.html.haml
@@ -0,0 +1,16 @@
+- if can?(current_user, :update_pages, @project) && @project.pages_custom_certificate
+ .panel.panel-default.panel.panel-danger
+ .panel-heading
+ Remove certificate
+ .errors-holder
+ .panel-body
+ = form_tag(certificates_namespace_project_pages_path(@project.namespace, @project), method: :delete, class: 'form-horizontal') do
+ %p
+ Removing the certificate will stop serving the page under HTTPS.
+ - if certificate
+ %p
+ %pre
+ = certificate.to_text
+
+ .form-actions
+ = button_to 'Remove certificate', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_pages_certificate_message(@project) }
diff --git a/app/views/projects/pages/_upload_certificate.html.haml b/app/views/projects/pages/_upload_certificate.html.haml
new file mode 100644
index 00000000000..30873fcf395
--- /dev/null
+++ b/app/views/projects/pages/_upload_certificate.html.haml
@@ -0,0 +1,32 @@
+- if can?(current_user, :update_pages, @project) && Settings.pages.https && Settings.pages.custom_domain
+ .panel.panel-default
+ .panel-heading
+ Certificate
+ .panel-body
+ %p
+ Allows you to upload your certificate which will be used to serve pages under your domain.
+ %br
+
+ = form_for [@project], url: namespace_project_pages_path(@project.namespace, @project), html: { class: 'form-horizontal fieldset-form' } do |f|
+ - if @project.errors.any?
+ #error_explanation
+ .alert.alert-danger
+ - @project.errors.full_messages.each do |msg|
+ %p= msg
+
+ .form-group
+ = f.label :pages_custom_certificate, class: 'control-label' do
+ Certificate (PEM)
+ .col-sm-10
+ = f.text_area :pages_custom_certificate, required: true, rows: 5, class: 'form-control', value: ''
+ %span.help-inline Upload a certificate for your domain with all intermediates
+
+ .form-group
+ = f.label :pages_custom_certificate_key, class: 'control-label' do
+ Key (PEM)
+ .col-sm-10
+ = f.text_area :pages_custom_certificate_key, required: true, rows: 5, class: 'form-control', value: ''
+ %span.help-inline Upload a certificate for your domain with all intermediates
+
+ .form-actions
+ = f.submit 'Update certificate', class: "btn btn-save"
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
new file mode 100644
index 00000000000..5542bbe670b
--- /dev/null
+++ b/app/views/projects/pages/_use.html.haml
@@ -0,0 +1,18 @@
+- unless @project.pages_url
+ .panel.panel-info
+ .panel-heading
+ Configure pages
+ .panel-body
+ %p
+ Learn how to upload your static site and have it served by
+ GitLab by following the #{link_to "documentation on GitLab Pages", "http://doc.gitlab.com/ee/pages/README.html", target: :blank}.
+ %p
+ In the example below we define a special job named
+ %code pages
+ which is using Jekyll to build a static site. The generated
+ HTML will be stored in the
+ %code public/
+ directory which will then be archived and uploaded to GitLab.
+ The name of the directory should not be different than
+ %code public/
+ in order for the pages to work.
diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml
new file mode 100644
index 00000000000..5f689800da8
--- /dev/null
+++ b/app/views/projects/pages/show.html.haml
@@ -0,0 +1,18 @@
+- page_title "Pages"
+%h3.page_title Pages
+%p.light
+ With GitLab Pages you can host for free your static websites on GitLab.
+ 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.
+%hr
+
+- if Settings.pages.enabled
+ = render 'access'
+ = render 'use'
+ - if @project.pages_url
+ = render 'form'
+ = render 'upload_certificate'
+ = render 'remove_certificate'
+ = render 'destroy'
+- else
+ = render 'disabled'
diff --git a/app/workers/pages_worker.rb b/app/workers/pages_worker.rb
index 8c99e8dbe76..4eeb9666bb0 100644
--- a/app/workers/pages_worker.rb
+++ b/app/workers/pages_worker.rb
@@ -9,7 +9,11 @@ class PagesWorker
def deploy(build_id)
build = Ci::Build.find_by(id: build_id)
- Projects::UpdatePagesService.new(build.project, build).execute
+ result = Projects::UpdatePagesService.new(build.project, build).execute
+ if result[:status] == :success
+ result = Projects::UpdatePagesConfigurationService.new(build.project).execute
+ end
+ result
end
def remove(namespace_path, project_path)
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 860cafad325..239aa662d9f 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -273,6 +273,7 @@ Settings.pages['https'] = false if Settings.pages['https'].nil?
Settings.pages['port'] ||= Settings.pages.https ? 443 : 80
Settings.pages['protocol'] ||= Settings.pages.https ? "https" : "http"
Settings.pages['url'] ||= Settings.send(:build_pages_url)
+Settings.pages['custom_domain'] ||= false if Settings.pages['custom_domain'].nil?
#
# Git LFS
diff --git a/config/routes/project.rb b/config/routes/project.rb
index cd56f6281f5..956a2d3186f 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -39,6 +39,10 @@ constraints(ProjectUrlConstrainer.new) do
end
end
+ resource :pages, only: [:show, :update, :destroy] do
+ delete :certificates
+ end
+
resources :compare, only: [:index, :create] do
collection do
get :diff_for_path
@@ -329,7 +333,6 @@ constraints(ProjectUrlConstrainer.new) do
post :archive
post :unarchive
post :housekeeping
- post :remove_pages
post :toggle_star
post :preview_markdown
post :export
diff --git a/db/migrate/20160209125808_add_pages_custom_domain_to_projects.rb b/db/migrate/20160209125808_add_pages_custom_domain_to_projects.rb
new file mode 100644
index 00000000000..6472199fc4a
--- /dev/null
+++ b/db/migrate/20160209125808_add_pages_custom_domain_to_projects.rb
@@ -0,0 +1,10 @@
+class AddPagesCustomDomainToProjects < ActiveRecord::Migration
+ def change
+ add_column :projects, :pages_custom_certificate, :text
+ add_column :projects, :pages_custom_certificate_key, :text
+ add_column :projects, :pages_custom_certificate_key_iv, :string
+ add_column :projects, :pages_custom_certificate_key_salt, :string
+ add_column :projects, :pages_custom_domain, :string, unique: true
+ add_column :projects, :pages_redirect_http, :boolean, default: false, null: false
+ end
+end