diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2019-04-24 13:54:46 +0200 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2019-04-24 14:48:52 +0200 |
commit | 5fc045114c9b6faf0e7f506f0af06b8ca3a2996b (patch) | |
tree | 69e8118885a933ab513ee207ee884cac088b4d35 | |
parent | 2a00858533f1dcae71e97ba52386bfb2bfc1f752 (diff) | |
download | gitlab-ce-pages-host-api.tar.gz |
Add `token`pages-host-api
-rw-r--r-- | app/models/project.rb | 36 | ||||
-rw-r--r-- | app/models/project_feature.rb | 4 | ||||
-rw-r--r-- | config/gitlab.yml.example | 1 | ||||
-rw-r--r-- | lib/api/entities.rb | 39 | ||||
-rw-r--r-- | lib/api/helpers.rb | 13 | ||||
-rw-r--r-- | lib/api/internals/pages.rb | 67 |
6 files changed, 93 insertions, 67 deletions
diff --git a/app/models/project.rb b/app/models/project.rb index 2e72de4e447..36b16a53fe8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1566,23 +1566,37 @@ class Project < ApplicationRecord def pages_group_url # The host in URL always needs to be downcased - Gitlab.config.pages.url.sub(%r{^https?://}) do |prefix| - "#{prefix}#{pages_subdomain}." - end.downcase + strong_memoize(:pages_group_url) do + Gitlab.config.pages.url.sub(%r{^https?://}) do |prefix| + "#{prefix}#{pages_subdomain}." + end.downcase + end end - def pages_url - url = pages_group_url - url_path = full_path.partition('/').last - - # If the project path is the same as host, we serve it as group page - return url if url == "#{Settings.pages.protocol}://#{url_path}" + def pages_group_root? + strong_memoize(:pages_group_root?) do + pages_group_url == "#{Settings.pages.protocol}://#{pages_path}" + end + end - "#{url}/#{url_path}" + def pages_url + if pages_group_root? + pages_group_url + else + "#{pages_group_url}/#{pages_path}" + end end def pages_subdomain - full_path.partition('/').first + strong_memoize(:pages_subdomain) do + full_path.partition('/').first + end + end + + def pages_path + strong_memoize(:pages_path) do + full_path.partition('/').drop(1).join('/') + end end def pages_path diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index 0542581c6e0..b6fb2c459bd 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -109,6 +109,10 @@ class ProjectFeature < ApplicationRecord pages_access_level == PUBLIC || pages_access_level == ENABLED && project.public? end + def private_pages? + !public_pages? + end + private # Validates builds and merge requests access level diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index bdac5b2a6a1..44cc051e94e 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -238,6 +238,7 @@ production: &base access_control: false # The location where pages are stored (default: shared/pages). # path: shared/pages + # token: internal-api-token # The domain under which the pages are served: # http://group.example.com/project diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ee8480122c4..22195c6a994 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1628,5 +1628,44 @@ module API class ClusterProject < Cluster expose :project, using: Entities::BasicProjectDetails end + + module Pages + class ProjectLookupPath < Grape::Entity + expose :pages_https_only?, as: :https_only + expose :id, as: :project_id + expose :private_pages?, as: :access_control + + expose :prefix do |project, opts| + if project.pages_root? + '/' + else + project.full_path.delete_prefix(opts[:prefix]) + '/' + end + end + + expose :path do |project| + "#{project.public_pages_path}/" + end + end + + class Domain < Grape::Entity + end + + class PagesDomain < Domain + expose :certificate + expose :key + + expose :lookup_paths, using: Pages::ProjectLookupPath do |domain| + [domain.project] + end + end + + class NamespaceDomain < Domain + expose :lookup_paths, using: Pages::ProjectLookupPath do |group| + group.all_projects.with_pages.select(&:pages_deployed?) + .sort_by(&:pages_url).reverse + end + end + end end end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 8a21d44b4bf..5c93021688b 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -212,13 +212,18 @@ module API authenticate! unless %w[GET HEAD].include?(route.request_method) end - def authenticate_by_gitlab_shell_token! + def secret_token_param input = params['secret_token'] input ||= Base64.decode64(headers[GITLAB_SHARED_SECRET_HEADER]) if headers.key?(GITLAB_SHARED_SECRET_HEADER) - input&.chomp! + end + + def authenticate_by_gitlab_shell_token! + unauthorized! unless Devise.secure_compare(shell_secret_token, secret_token_param) + end - unauthorized! unless Devise.secure_compare(secret_token, input) + def authenticate_by_gitlab_pages_token! + unauthorized! unless Devise.secure_compare(Gitlab.pages.token, secret_token_param) end def authenticated_with_full_private_access! @@ -501,7 +506,7 @@ module API @sudo_identifier ||= params[SUDO_PARAM] || env[SUDO_HEADER] end - def secret_token + def shell_secret_token Gitlab::Shell.secret_token end diff --git a/lib/api/internals/pages.rb b/lib/api/internals/pages.rb index a8631827b3d..1f0d5a99d83 100644 --- a/lib/api/internals/pages.rb +++ b/lib/api/internals/pages.rb @@ -3,15 +3,21 @@ module API module Internals class Pages < Grape::API + before { authenticate_by_gitlab_pages_token! } + namespace 'internals' do params do requires :host, type: String, desc: 'The Pages host' end get 'pages/query' do - if namespace_name = find_namespace_name(params[:host]) - namespace_domain(namespace_name, params[:host].downcase) - elsif domain = find_user_domain(params[:host]) - user_domain(domain) + if namespace = find_namespace(params[:host]) + render namespace, + using: API::Entities::Pages::NamespaceDomain, + prefix: namespace.full_path + elsif domain = find_pages_domain(params[:host]) + render domain, + using: API::Entities::Pages::PagesDomain, + prefix: domain.project.full_path else status :not_found end @@ -19,62 +25,19 @@ module API end helpers do - def namespace_domain(namespace_name, host) - lookup_paths = [] - - if namespace = Namespace.find_by_full_path(namespace_name) - namespace.all_projects.with_pages.each do |project| - prefix = project.full_path.delete_prefix(namespace.full_path) - lookup_paths << project_params(project, prefix) - end - - lookup_paths << namespace_project_params(namespace, host, "") - end - - status :ok - - { lookup_paths: lookup_paths.compact } - end - - def user_domain(domain) - lookup_paths = [] - lookup_paths << project_params(domain.project, "") - - status :ok - - { - certificate: domain.certificate, - key: domain.certificate_key, - lookup_paths: lookup_paths.compact - } - end - def find_namespace_name(host) host = host.downcase gitlab_host = "." + ::Settings.pages.host.downcase host.delete_suffix(gitlab_host) if host.ends_with?(gitlab_host) end - def find_user_domain(host) - PagesDomain.find_by(domain: host.downcase) - end - - def namespace_project_params(namespace, project_name, prefix) - project = namespace.projects.with_pages.find_by(path: project_name) - project_params(project, prefix) + def find_namespace(host) + namespace_name = find_namespace_name(host) + Namespace.find_by_full_path(namespace_name) if namespace_name end - def project_params(project, prefix) - return unless project - return unless project.pages_deployed? - - { - https_only: project.pages_https_only?, - project_id: project.project_id, - access_control: !project.public_pages?, - prefix: "#{prefix}/", - path: "#{project.public_pages_path}/" - } + def find_pages_domain(host) + PagesDomain.find_by(domain: host.downcase) end end end |