Commit 9200b500 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '39436-pages-api-administrative' into 'master'

Add administrative endpoint to list all pages domains

Closes #39436

See merge request gitlab-org/gitlab-ce!15160
parents e897d8b7 1162d89a
...@@ -69,6 +69,10 @@ class PagesDomain < ActiveRecord::Base ...@@ -69,6 +69,10 @@ class PagesDomain < ActiveRecord::Base
current < x509.not_before || x509.not_after < current current < x509.not_before || x509.not_after < current
end end
def expiration
x509&.not_after
end
def subject def subject
return unless x509 return unless x509
x509.subject.to_s x509.subject.to_s
......
---
title: Add administrative endpoint to list all pages domains
merge_request: 15160
author: Travis Miller
type: added
...@@ -4,6 +4,31 @@ Endpoints for connecting custom domain(s) and TLS certificates in [GitLab Pages] ...@@ -4,6 +4,31 @@ Endpoints for connecting custom domain(s) and TLS certificates in [GitLab Pages]
The GitLab Pages feature must be enabled to use these endpoints. Find out more about [administering](../administration/pages/index.md) and [using](../user/project/pages/index.md) the feature. The GitLab Pages feature must be enabled to use these endpoints. Find out more about [administering](../administration/pages/index.md) and [using](../user/project/pages/index.md) the feature.
## List all pages domains
Get a list of all pages domains. The user must have admin permissions.
```http
GET /pages/domains
```
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/pages/domains
```
```json
[
{
"domain": "ssl.domain.example",
"url": "https://ssl.domain.example",
"certificate": {
"expired": false,
"expiration": "2020-04-12T14:32:00.000Z"
}
}
]
```
## List pages domains ## List pages domains
Get a list of project pages domains. The user must have permissions to view pages domains. Get a list of project pages domains. The user must have permissions to view pages domains.
......
...@@ -1042,6 +1042,11 @@ module API ...@@ -1042,6 +1042,11 @@ module API
expose :value expose :value
end end
class PagesDomainCertificateExpiration < Grape::Entity
expose :expired?, as: :expired
expose :expiration
end
class PagesDomainCertificate < Grape::Entity class PagesDomainCertificate < Grape::Entity
expose :subject expose :subject
expose :expired?, as: :expired expose :expired?, as: :expired
...@@ -1049,12 +1054,23 @@ module API ...@@ -1049,12 +1054,23 @@ module API
expose :certificate_text expose :certificate_text
end end
class PagesDomainBasic < Grape::Entity
expose :domain
expose :url
expose :certificate,
as: :certificate_expiration,
if: ->(pages_domain, _) { pages_domain.certificate? },
using: PagesDomainCertificateExpiration do |pages_domain|
pages_domain
end
end
class PagesDomain < Grape::Entity class PagesDomain < Grape::Entity
expose :domain expose :domain
expose :url expose :url
expose :certificate, expose :certificate,
if: ->(pages_domain, _) { pages_domain.certificate? }, if: ->(pages_domain, _) { pages_domain.certificate? },
using: PagesDomainCertificate do |pages_domain| using: PagesDomainCertificate do |pages_domain|
pages_domain pages_domain
end end
end end
......
...@@ -155,6 +155,11 @@ module API ...@@ -155,6 +155,11 @@ module API
end end
end end
def authenticated_with_full_private_access!
authenticate!
forbidden! unless current_user.full_private_access?
end
def authenticated_as_admin! def authenticated_as_admin!
authenticate! authenticate!
forbidden! unless current_user.admin? forbidden! unless current_user.admin?
...@@ -190,6 +195,10 @@ module API ...@@ -190,6 +195,10 @@ module API
not_found! unless user_project.pages_available? not_found! unless user_project.pages_available?
end end
def require_pages_config_enabled!
not_found! unless Gitlab.config.pages.enabled
end
def can?(object, action, subject = :global) def can?(object, action, subject = :global)
Ability.allowed?(object, action, subject) Ability.allowed?(object, action, subject)
end end
......
...@@ -4,7 +4,6 @@ module API ...@@ -4,7 +4,6 @@ module API
before do before do
authenticate! authenticate!
require_pages_enabled!
end end
after_validation do after_validation do
...@@ -29,10 +28,31 @@ module API ...@@ -29,10 +28,31 @@ module API
end end
end end
resource :pages do
before do
require_pages_config_enabled!
authenticated_with_full_private_access!
end
desc "Get all pages domains" do
success Entities::PagesDomainBasic
end
params do
use :pagination
end
get "domains" do
present paginate(PagesDomain.all), with: Entities::PagesDomainBasic
end
end
params do params do
requires :id, type: String, desc: 'The ID of a project' requires :id, type: String, desc: 'The ID of a project'
end end
resource :projects, requirements: { id: %r{[^/]+} } do resource :projects, requirements: { id: %r{[^/]+} } do
before do
require_pages_enabled!
end
desc 'Get all pages domains' do desc 'Get all pages domains' do
success Entities::PagesDomain success Entities::PagesDomain
end end
......
{
"type": "object",
"properties": {
"domain": { "type": "string" },
"url": { "type": "uri" },
"certificate_expiration": {
"type": "object",
"properties": {
"expired": { "type": "boolean" },
"expiration": { "type": "string" }
},
"required": ["expired", "expiration"],
"additionalProperties": false
}
},
"required": ["domain", "url"],
"additionalProperties": false
}
{
"type": "object",
"properties": {
"domain": { "type": "string" },
"url": { "type": "uri" },
"certificate": {
"type": "object",
"properties": {
"subject": { "type": "string" },
"expired": { "type": "boolean" },
"certificate": { "type": "string" },
"certificate_text": { "type": "string" }
},
"required": ["subject", "expired"],
"additionalProperties": false
}
},
"required": ["domain", "url"],
"additionalProperties": false
}
{
"type": "array",
"items": { "$ref": "pages_domain/basic.json" }
}
{ {
"type": "array", "type": "array",
"items": { "items": { "$ref": "pages_domain/detail.json" }
"type": "object",
"properties": {
"domain": { "type": "string" },
"url": { "type": "uri" },
"certificate": {
"type": "object",
"properties": {
"subject": { "type": "string" },
"expired": { "type": "boolean" },
"certificate": { "type": "string" },
"certificate_text": { "type": "string" }
},
"required": ["subject", "expired"],
"additionalProperties": false
}
},
"required": ["domain", "url"],
"additionalProperties": false
}
} }
...@@ -3,6 +3,7 @@ require 'rails_helper' ...@@ -3,6 +3,7 @@ require 'rails_helper'
describe API::PagesDomains do describe API::PagesDomains do
set(:project) { create(:project) } set(:project) { create(:project) }
set(:user) { create(:user) } set(:user) { create(:user) }
set(:admin) { create(:admin) }
set(:pages_domain) { create(:pages_domain, domain: 'www.domain.test', project: project) } set(:pages_domain) { create(:pages_domain, domain: 'www.domain.test', project: project) }
set(:pages_domain_secure) { create(:pages_domain, :with_certificate, :with_key, domain: 'ssl.domain.test', project: project) } set(:pages_domain_secure) { create(:pages_domain, :with_certificate, :with_key, domain: 'ssl.domain.test', project: project) }
...@@ -23,12 +24,49 @@ describe API::PagesDomains do ...@@ -23,12 +24,49 @@ describe API::PagesDomains do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true) allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
end end
describe 'GET /pages/domains' do
context 'when pages is disabled' do
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(false)
end
it_behaves_like '404 response' do
let(:request) { get api('/pages/domains', admin) }
end
end
context 'when pages is enabled' do
context 'when authenticated as an admin' do
it 'returns paginated all pages domains' do
get api('/pages/domains', admin)
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain_basics')
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(3)
expect(json_response.last).to have_key('domain')
expect(json_response.last).to have_key('certificate_expiration')
expect(json_response.last['certificate_expiration']['expired']).to be true
expect(json_response.first).not_to have_key('certificate_expiration')
end
end
context 'when authenticated as a non-member' do
it_behaves_like '403 response' do
let(:request) { get api('/pages/domains', user) }
end
end
end
end
describe 'GET /projects/:project_id/pages/domains' do describe 'GET /projects/:project_id/pages/domains' do
shared_examples_for 'get pages domains' do shared_examples_for 'get pages domains' do
it 'returns paginated pages domains' do it 'returns paginated pages domains' do
get api(route, user) get api(route, user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domains')
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.size).to eq(3) expect(json_response.size).to eq(3)
...@@ -99,6 +137,7 @@ describe API::PagesDomains do ...@@ -99,6 +137,7 @@ describe API::PagesDomains do
get api(route_domain, user) get api(route_domain, user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(json_response['domain']).to eq(pages_domain.domain) expect(json_response['domain']).to eq(pages_domain.domain)
expect(json_response['url']).to eq(pages_domain.url) expect(json_response['url']).to eq(pages_domain.url)
expect(json_response['certificate']).to be_nil expect(json_response['certificate']).to be_nil
...@@ -108,6 +147,7 @@ describe API::PagesDomains do ...@@ -108,6 +147,7 @@ describe API::PagesDomains do
get api(route_secure_domain, user) get api(route_secure_domain, user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(json_response['domain']).to eq(pages_domain_secure.domain) expect(json_response['domain']).to eq(pages_domain_secure.domain)
expect(json_response['url']).to eq(pages_domain_secure.url) expect(json_response['url']).to eq(pages_domain_secure.url)
expect(json_response['certificate']['subject']).to eq(pages_domain_secure.subject) expect(json_response['certificate']['subject']).to eq(pages_domain_secure.subject)
...@@ -118,6 +158,7 @@ describe API::PagesDomains do ...@@ -118,6 +158,7 @@ describe API::PagesDomains do
get api(route_expired_domain, user) get api(route_expired_domain, user)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(json_response['certificate']['expired']).to be true expect(json_response['certificate']['expired']).to be true
end end
end end
...@@ -187,6 +228,7 @@ describe API::PagesDomains do ...@@ -187,6 +228,7 @@ describe API::PagesDomains do
pages_domain = PagesDomain.find_by(domain: json_response['domain']) pages_domain = PagesDomain.find_by(domain: json_response['domain'])
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain.domain).to eq(params[:domain]) expect(pages_domain.domain).to eq(params[:domain])
expect(pages_domain.certificate).to be_nil expect(pages_domain.certificate).to be_nil
expect(pages_domain.key).to be_nil expect(pages_domain.key).to be_nil
...@@ -197,6 +239,7 @@ describe API::PagesDomains do ...@@ -197,6 +239,7 @@ describe API::PagesDomains do
pages_domain = PagesDomain.find_by(domain: json_response['domain']) pages_domain = PagesDomain.find_by(domain: json_response['domain'])
expect(response).to have_gitlab_http_status(201) expect(response).to have_gitlab_http_status(201)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain.domain).to eq(params_secure[:domain]) expect(pages_domain.domain).to eq(params_secure[:domain])
expect(pages_domain.certificate).to eq(params_secure[:certificate]) expect(pages_domain.certificate).to eq(params_secure[:certificate])
expect(pages_domain.key).to eq(params_secure[:key]) expect(pages_domain.key).to eq(params_secure[:key])
...@@ -270,6 +313,7 @@ describe API::PagesDomains do ...@@ -270,6 +313,7 @@ describe API::PagesDomains do
pages_domain_secure.reload pages_domain_secure.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain_secure.certificate).to be_nil expect(pages_domain_secure.certificate).to be_nil
expect(pages_domain_secure.key).to be_nil expect(pages_domain_secure.key).to be_nil
end end
...@@ -279,6 +323,7 @@ describe API::PagesDomains do ...@@ -279,6 +323,7 @@ describe API::PagesDomains do
pages_domain.reload pages_domain.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain.certificate).to eq(params_secure[:certificate]) expect(pages_domain.certificate).to eq(params_secure[:certificate])
expect(pages_domain.key).to eq(params_secure[:key]) expect(pages_domain.key).to eq(params_secure[:key])
end end
...@@ -288,6 +333,7 @@ describe API::PagesDomains do ...@@ -288,6 +333,7 @@ describe API::PagesDomains do
pages_domain_expired.reload pages_domain_expired.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain_expired.certificate).to eq(params_secure[:certificate]) expect(pages_domain_expired.certificate).to eq(params_secure[:certificate])
expect(pages_domain_expired.key).to eq(params_secure[:key]) expect(pages_domain_expired.key).to eq(params_secure[:key])
end end
...@@ -297,6 +343,7 @@ describe API::PagesDomains do ...@@ -297,6 +343,7 @@ describe API::PagesDomains do
pages_domain_secure.reload pages_domain_secure.reload
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
expect(pages_domain_secure.certificate).to eq(params_secure_nokey[:certificate]) expect(pages_domain_secure.certificate).to eq(params_secure_nokey[:certificate])
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment