Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
867151ac
Commit
867151ac
authored
Mar 04, 2020
by
Sean Arnold
Committed by
Heinrich Lee Yu
Mar 04, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add StatusPageSetting model
- Migration - EE model & factory
parent
7a0cfc82
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
383 additions
and
4 deletions
+383
-4
changelogs/unreleased/207181-status-page-settings-backend.yml
...gelogs/unreleased/207181-status-page-settings-backend.yml
+5
-0
db/migrate/20200224020219_add_status_page_settings.rb
db/migrate/20200224020219_add_status_page_settings.rb
+18
-0
db/schema.rb
db/schema.rb
+13
-0
ee/app/controllers/ee/projects/settings/operations_controller.rb
...controllers/ee/projects/settings/operations_controller.rb
+6
-0
ee/app/helpers/operations_helper.rb
ee/app/helpers/operations_helper.rb
+10
-0
ee/app/models/ee/project.rb
ee/app/models/ee/project.rb
+2
-0
ee/app/models/status_page_setting.rb
ee/app/models/status_page_setting.rb
+45
-0
ee/app/services/ee/projects/operations/update_service.rb
ee/app/services/ee/projects/operations/update_service.rb
+12
-0
ee/spec/controllers/projects/settings/operations_controller_spec.rb
...ntrollers/projects/settings/operations_controller_spec.rb
+55
-4
ee/spec/factories/status_page_settings.rb
ee/spec/factories/status_page_settings.rb
+16
-0
ee/spec/helpers/ee/operations_helper_spec.rb
ee/spec/helpers/ee/operations_helper_spec.rb
+42
-0
ee/spec/models/project_spec.rb
ee/spec/models/project_spec.rb
+1
-0
ee/spec/models/status_page_setting_spec.rb
ee/spec/models/status_page_setting_spec.rb
+76
-0
ee/spec/services/projects/operations/update_service_spec.rb
ee/spec/services/projects/operations/update_service_spec.rb
+81
-0
spec/lib/gitlab/import_export/all_models.yml
spec/lib/gitlab/import_export/all_models.yml
+1
-0
No files found.
changelogs/unreleased/207181-status-page-settings-backend.yml
0 → 100644
View file @
867151ac
---
title
:
Create table & setup operations endpoint for Status Page Settings
merge_request
:
25863
author
:
type
:
added
db/migrate/20200224020219_add_status_page_settings.rb
0 → 100644
View file @
867151ac
# frozen_string_literal: true
class
AddStatusPageSettings
<
ActiveRecord
::
Migration
[
6.0
]
DOWNTIME
=
false
def
change
create_table
:status_page_settings
,
id:
false
do
|
t
|
t
.
references
:project
,
index:
true
,
primary_key:
true
,
foreign_key:
{
on_delete: :cascade
},
unique:
true
,
null:
false
t
.
timestamps_with_timezone
null:
false
t
.
boolean
:enabled
,
default:
false
,
null:
false
t
.
string
:aws_s3_bucket_name
,
limit:
63
,
null:
false
t
.
string
:aws_region
,
limit:
255
,
null:
false
t
.
string
:aws_access_key
,
limit:
255
,
null:
false
t
.
string
:encrypted_aws_secret_key
,
limit:
255
,
null:
false
t
.
string
:encrypted_aws_secret_key_iv
,
limit:
255
,
null:
false
end
end
end
db/schema.rb
View file @
867151ac
...
...
@@ -4002,6 +4002,18 @@ ActiveRecord::Schema.define(version: 2020_02_27_165129) do
t
.
boolean
"recaptcha_verified"
,
default:
false
,
null:
false
end
create_table
"status_page_settings"
,
primary_key:
"project_id"
,
force: :cascade
do
|
t
|
t
.
datetime_with_timezone
"created_at"
,
null:
false
t
.
datetime_with_timezone
"updated_at"
,
null:
false
t
.
boolean
"enabled"
,
default:
false
,
null:
false
t
.
string
"aws_s3_bucket_name"
,
limit:
63
,
null:
false
t
.
string
"aws_region"
,
limit:
255
,
null:
false
t
.
string
"aws_access_key"
,
limit:
255
,
null:
false
t
.
string
"encrypted_aws_secret_key"
,
limit:
255
,
null:
false
t
.
string
"encrypted_aws_secret_key_iv"
,
limit:
255
,
null:
false
t
.
index
[
"project_id"
],
name:
"index_status_page_settings_on_project_id"
end
create_table
"subscriptions"
,
id: :serial
,
force: :cascade
do
|
t
|
t
.
integer
"user_id"
t
.
integer
"subscribable_id"
...
...
@@ -5018,6 +5030,7 @@ ActiveRecord::Schema.define(version: 2020_02_27_165129) do
add_foreign_key
"snippets"
,
"projects"
,
name:
"fk_be41fd4bb7"
,
on_delete: :cascade
add_foreign_key
"software_license_policies"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"software_license_policies"
,
"software_licenses"
,
on_delete: :cascade
add_foreign_key
"status_page_settings"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"subscriptions"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"suggestions"
,
"notes"
,
on_delete: :cascade
add_foreign_key
"system_note_metadata"
,
"description_versions"
,
name:
"fk_fbd87415c9"
,
on_delete: :nullify
...
...
ee/app/controllers/ee/projects/settings/operations_controller.rb
View file @
867151ac
...
...
@@ -58,9 +58,15 @@ module EE
permitted_params
[
:tracing_setting_attributes
]
=
[
:external_url
]
end
permitted_params
.
merge!
(
status_page_setting_params
)
permitted_params
end
def
status_page_setting_params
{
status_page_setting_attributes:
[
:aws_s3_bucket_name
,
:aws_region
,
:aws_access_key
,
:aws_secret_key
,
:enabled
]
}
end
override
:track_events
def
track_events
(
result
)
super
...
...
ee/app/helpers/operations_helper.rb
View file @
867151ac
...
...
@@ -19,4 +19,14 @@ module OperationsHelper
'environments-dashboard-help-path'
=>
help_page_path
(
'ci/environments/environments_dashboard.md'
)
}
end
def
status_page_settings_data
(
status_page_setting
)
{
'setting-enabled'
=>
status_page_setting
&
.
enabled?
,
'setting-aws-access-key'
=>
status_page_setting
&
.
aws_access_key
,
'setting-masked-aws-secret-key'
=>
status_page_setting
&
.
masked_aws_secret_key
,
'setting-aws-region'
=>
status_page_setting
&
.
aws_region
,
'setting-aws-s3-bucket-name'
=>
status_page_setting
&
.
aws_s3_bucket_name
}
end
end
ee/app/models/ee/project.rb
View file @
867151ac
...
...
@@ -48,6 +48,7 @@ module EE
has_one
:tracing_setting
,
class_name:
'ProjectTracingSetting'
has_one
:alerting_setting
,
inverse_of: :project
,
class_name:
'Alerting::ProjectAlertingSetting'
has_one
:feature_usage
,
class_name:
'ProjectFeatureUsage'
has_one
:status_page_setting
,
inverse_of: :project
has_many
:reviews
,
inverse_of: :project
has_many
:approvers
,
as: :target
,
dependent: :destroy
# rubocop:disable Cop/ActiveRecordDependent
...
...
@@ -179,6 +180,7 @@ module EE
accepts_nested_attributes_for
:tracing_setting
,
update_only:
true
,
allow_destroy:
true
accepts_nested_attributes_for
:alerting_setting
,
update_only:
true
accepts_nested_attributes_for
:status_page_setting
,
update_only:
true
,
allow_destroy:
true
alias_attribute
:fallback_approvals_required
,
:approvals_before_merge
end
...
...
ee/app/models/status_page_setting.rb
0 → 100644
View file @
867151ac
# frozen_string_literal: true
class
StatusPageSetting
<
ApplicationRecord
# AWS validations. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25863#note_295772553
AWS_BUCKET_NAME_REGEXP
=
/\A[a-z0-9][a-z0-9\-.]*\z/
.
freeze
AWS_ACCESS_KEY_REGEXP
=
/\A[A-Z0-9]{20}\z/
.
freeze
AWS_SECRET_KEY_REGEXP
=
/\A[A-Za-z0-9\/+=]{40}\z/
.
freeze
belongs_to
:project
attr_encrypted
:aws_secret_key
,
mode: :per_attribute_iv
,
algorithm:
'aes-256-gcm'
,
key:
Settings
.
attr_encrypted_db_key_base_32
before_validation
:check_secret_changes
validates
:aws_s3_bucket_name
,
length:
{
minimum:
3
,
maximum:
63
},
presence:
true
,
format:
{
with:
AWS_BUCKET_NAME_REGEXP
}
validates
:aws_access_key
,
presence:
true
,
format:
{
with:
AWS_ACCESS_KEY_REGEXP
}
validates
:aws_secret_key
,
presence:
true
,
format:
{
with:
AWS_SECRET_KEY_REGEXP
}
validates
:project
,
:aws_region
,
:encrypted_aws_secret_key
,
presence:
true
validates
:enabled
,
inclusion:
{
in:
[
true
,
false
]
}
scope
:enabled
,
->
{
where
(
enabled:
true
)
}
def
masked_aws_secret_key
'*'
*
40
end
private
def
check_secret_changes
return
unless
masked_aws_secret_key
==
aws_secret_key
restore_attributes
[
:aws_secret_key
,
:encrypted_aws_secret_key
,
:encrypted_aws_secret_key_iv
]
end
end
ee/app/services/ee/projects/operations/update_service.rb
View file @
867151ac
...
...
@@ -13,6 +13,7 @@ module EE
.
merge
(
tracing_setting_params
)
.
merge
(
alerting_setting_params
)
.
merge
(
incident_management_setting_params
)
.
merge
(
status_page_setting_params
)
end
private
...
...
@@ -46,6 +47,17 @@ module EE
def
incident_management_setting_params
params
.
slice
(
:incident_management_setting_attributes
)
end
def
status_page_setting_params
return
{}
unless
attrs
=
params
[
:status_page_setting_attributes
]
destroy
=
attrs
[
:aws_s3_bucket_name
].
blank?
&&
attrs
[
:aws_region
].
blank?
&&
attrs
[
:aws_access_key
].
blank?
&&
attrs
[
:aws_secret_key
].
blank?
{
status_page_setting_attributes:
attrs
.
merge
(
_destroy:
destroy
)
}
end
end
end
end
...
...
ee/spec/controllers/projects/settings/operations_controller_spec.rb
View file @
867151ac
...
...
@@ -271,6 +271,55 @@ describe Projects::Settings::OperationsController do
update_project
(
project
,
tracing_params:
{
external_url:
"http://example.com"
}
)
end
end
context
'without existing status page setting'
do
let
(
:project
)
{
create
(
:project
)
}
before
do
project
.
add_maintainer
(
user
)
end
it
'creates a status page setting'
do
valid_attributes
=
attributes_for
(
:status_page_setting
).
except
(
:enabled
)
update_project
(
project
,
status_page_params:
valid_attributes
)
expect
(
project
.
status_page_setting
).
not_to
eq
(
nil
)
expect
(
project
.
status_page_setting
).
to
be_a
(
StatusPageSetting
)
end
end
context
'with existing status page setting'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:status_page_attributes
)
{
attributes_for
(
:status_page_setting
)
}
before
do
project
.
add_maintainer
(
user
)
project
.
create_status_page_setting!
(
status_page_attributes
)
end
it
'updates the fields'
do
update_project
(
project
,
status_page_params:
status_page_attributes
.
merge
(
aws_s3_bucket_name:
'test'
))
expect
(
project
.
status_page_setting
.
aws_s3_bucket_name
).
to
eq
(
'test'
)
end
it
'respects the model validations'
do
old_name
=
project
.
status_page_setting
.
aws_s3_bucket_name
update_project
(
project
,
status_page_params:
status_page_attributes
.
merge
(
aws_s3_bucket_name:
''
))
expect
(
project
.
status_page_setting
.
aws_s3_bucket_name
).
to
eq
(
old_name
)
end
it
'deletes the setting if keys removed'
do
update_project
(
project
,
status_page_params:
status_page_attributes
.
merge
(
aws_access_key:
''
,
aws_secret_key:
''
,
aws_s3_bucket_name:
''
,
aws_region:
''
)
)
expect
(
project
.
status_page_setting
).
to
be_nil
end
end
end
context
'without a license'
do
...
...
@@ -285,11 +334,12 @@ describe Projects::Settings::OperationsController do
private
def
update_project
(
project
,
tracing_params:
nil
,
incident_management_params:
nil
)
def
update_project
(
project
,
tracing_params:
nil
,
incident_management_params:
nil
,
status_page_params:
nil
)
patch
:update
,
params:
project_params
(
project
,
tracing_params:
tracing_params
,
incident_management_params:
incident_management_params
incident_management_params:
incident_management_params
,
status_page_params:
status_page_params
)
project
.
reload
...
...
@@ -399,13 +449,14 @@ describe Projects::Settings::OperationsController do
private
def
project_params
(
project
,
tracing_params:
nil
,
incident_management_params:
nil
)
def
project_params
(
project
,
tracing_params:
nil
,
incident_management_params:
nil
,
status_page_params:
nil
)
{
namespace_id:
project
.
namespace
,
project_id:
project
,
project:
{
tracing_setting_attributes:
tracing_params
,
incident_management_setting_attributes:
incident_management_params
incident_management_setting_attributes:
incident_management_params
,
status_page_setting_attributes:
status_page_params
}
}
end
...
...
ee/spec/factories/status_page_settings.rb
0 → 100644
View file @
867151ac
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:status_page_setting
,
class:
'StatusPageSetting'
do
project
aws_s3_bucket_name
{
'bucket-name'
}
aws_region
{
'ap-southeast-2'
}
aws_access_key
{
FFaker
::
String
.
from_regexp
(
StatusPageSetting
::
AWS_ACCESS_KEY_REGEXP
)
}
aws_secret_key
{
FFaker
::
String
.
from_regexp
(
StatusPageSetting
::
AWS_SECRET_KEY_REGEXP
)
}
enabled
{
false
}
trait
:enabled
do
enabled
{
true
}
end
end
end
ee/spec/helpers/ee/operations_helper_spec.rb
0 → 100644
View file @
867151ac
# frozen_string_literal: true
require
'spec_helper'
describe
OperationsHelper
do
describe
'#status_page_settings_data'
do
subject
{
helper
.
status_page_settings_data
(
status_page_setting
)
}
context
'setting does not exist'
do
let
(
:status_page_setting
)
{
nil
}
it
'returns the correct values'
do
expect
(
subject
.
keys
)
.
to
contain_exactly
(
'setting-enabled'
,
'setting-aws-access-key'
,
'setting-masked-aws-secret-key'
,
'setting-aws-region'
,
'setting-aws-s3-bucket-name'
)
end
it
'returns nil for the values'
do
expect
(
subject
.
values
.
uniq
).
to
contain_exactly
(
nil
)
end
end
context
'setting exists'
do
let
(
:status_page_setting
)
{
create
(
:status_page_setting
)
}
it
'returns the correct values'
do
aggregate_failures
do
expect
(
subject
[
'setting-enabled'
]).
to
eq
(
status_page_setting
.
enabled
)
expect
(
subject
[
'setting-aws-access-key'
]).
to
eq
(
status_page_setting
.
aws_access_key
)
expect
(
subject
[
'setting-masked-aws-secret-key'
]).
to
eq
(
status_page_setting
.
masked_aws_secret_key
)
expect
(
subject
[
'setting-aws-region'
]).
to
eq
(
status_page_setting
.
aws_region
)
expect
(
subject
[
'setting-aws-s3-bucket-name'
]).
to
eq
(
status_page_setting
.
aws_s3_bucket_name
)
end
end
end
end
end
ee/spec/models/project_spec.rb
View file @
867151ac
...
...
@@ -23,6 +23,7 @@ describe Project do
it
{
is_expected
.
to
have_one
(
:import_state
).
class_name
(
'ProjectImportState'
)
}
it
{
is_expected
.
to
have_one
(
:repository_state
).
class_name
(
'ProjectRepositoryState'
).
inverse_of
(
:project
)
}
it
{
is_expected
.
to
have_one
(
:alerting_setting
).
class_name
(
'Alerting::ProjectAlertingSetting'
)
}
it
{
is_expected
.
to
have_one
(
:status_page_setting
).
class_name
(
'StatusPageSetting'
)
}
it
{
is_expected
.
to
have_many
(
:reviews
).
inverse_of
(
:project
)
}
it
{
is_expected
.
to
have_many
(
:path_locks
)
}
...
...
ee/spec/models/status_page_setting_spec.rb
0 → 100644
View file @
867151ac
# frozen_string_literal: true
require
'spec_helper'
describe
StatusPageSetting
do
describe
'associations'
do
it
{
is_expected
.
to
belong_to
(
:project
)
}
end
describe
'validations'
do
it
{
is_expected
.
to
validate_presence_of
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
to
validate_length_of
(
:aws_s3_bucket_name
).
is_at_least
(
3
).
is_at_most
(
63
)
}
it
{
is_expected
.
to
validate_presence_of
(
:aws_region
)
}
it
{
is_expected
.
to
validate_presence_of
(
:aws_access_key
)
}
it
{
is_expected
.
to
validate_presence_of
(
:encrypted_aws_secret_key
)
}
describe
'aws_s3_bucket_name'
do
it
{
is_expected
.
to
allow_value
(
'bucket-name'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
to
allow_value
(
'3ucket-name'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
to
allow_value
(
'bucket.name'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
to
allow_value
(
'b'
*
63
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
to
allow_value
(
'1'
*
63
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
not_to
allow_value
(
'Bucket-name'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
not_to
allow_value
(
'bucKet-Name'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
not_to
allow_value
(
'bb'
).
for
(
:aws_s3_bucket_name
)
}
it
{
is_expected
.
not_to
allow_value
(
'b'
*
64
).
for
(
:aws_s3_bucket_name
)
}
end
describe
'aws_access_key'
do
it
{
is_expected
.
to
allow_value
(
'A'
*
20
).
for
(
:aws_access_key
)
}
it
{
is_expected
.
to
allow_value
(
'1'
*
20
).
for
(
:aws_access_key
)
}
it
{
is_expected
.
not_to
allow_value
(
'A'
*
19
).
for
(
:aws_access_key
)
}
it
{
is_expected
.
not_to
allow_value
(
'1'
*
19
).
for
(
:aws_access_key
)
}
it
{
is_expected
.
not_to
allow_value
(
'A'
*
21
).
for
(
:aws_access_key
)
}
it
{
is_expected
.
not_to
allow_value
(
'1'
*
21
).
for
(
:aws_access_key
)
}
end
describe
'aws_secret_key'
do
let
(
:status_page_setting
)
{
build
(
:status_page_setting
)
}
it
'tests the validation'
do
expect
(
status_page_setting
.
valid?
).
to
eq
(
true
)
status_page_setting
.
aws_secret_key
=
'a'
*
40
expect
(
status_page_setting
.
valid?
).
to
eq
(
true
)
status_page_setting
.
aws_secret_key
=
'a'
*
39
expect
(
status_page_setting
.
valid?
).
to
eq
(
false
)
status_page_setting
.
aws_secret_key
=
'a'
*
41
expect
(
status_page_setting
.
valid?
).
to
eq
(
false
)
end
context
'existing setting'
do
let
(
:status_page_setting
)
{
create
(
:status_page_setting
)
}
it
'passes validation and removes changes if setting to masked key'
do
status_page_setting
.
aws_secret_key
=
status_page_setting
.
masked_aws_secret_key
expect
(
status_page_setting
.
valid?
).
to
eq
(
true
)
end
end
end
end
describe
'attribute encryption'
do
let
(
:new_secret
)
{
FFaker
::
String
.
from_regexp
(
StatusPageSetting
::
AWS_SECRET_KEY_REGEXP
)
}
subject
(
:status_page_setting
)
{
create
(
:status_page_setting
,
aws_secret_key:
new_secret
)
}
context
'token'
do
it
'encrypts original value into encrypted_token attribute'
do
expect
(
status_page_setting
.
encrypted_aws_secret_key
).
not_to
be_nil
end
end
end
end
ee/spec/services/projects/operations/update_service_spec.rb
View file @
867151ac
...
...
@@ -188,5 +188,86 @@ describe Projects::Operations::UpdateService do
it_behaves_like
'no operation'
end
end
context
'status page setting'
do
before
do
project
.
add_maintainer
(
user
)
end
shared_examples
'no operation'
do
it
'does nothing'
do
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
reload
.
status_page_setting
).
to
be_nil
end
end
context
'with valid params'
do
let
(
:params
)
do
{
status_page_setting_attributes:
attributes_for
(
:status_page_setting
,
aws_s3_bucket_name:
'test'
)
}
end
context
'with an existing setting'
do
before
do
create
(
:status_page_setting
,
project:
project
)
end
it
'updates the setting'
do
expect
(
project
.
status_page_setting
).
not_to
be_nil
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
reload
.
status_page_setting
.
aws_s3_bucket_name
)
.
to
eq
(
'test'
)
end
context
'with aws key and secret blank'
do
let
(
:params
)
do
{
status_page_setting_attributes:
{
aws_access_key:
''
,
aws_secret_key:
''
,
aws_s3_bucket_name:
''
,
aws_region:
''
}
}
end
it
'destroys the status_page_setting entry in DB'
do
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
reload
.
status_page_setting
).
to
be_nil
end
end
context
'with not all keys blank'
do
let
(
:params
)
do
{
status_page_setting_attributes:
{
aws_s3_bucket_name:
'test'
,
aws_region:
'ap-southeast-2'
,
aws_access_key:
''
,
aws_secret_key:
project
.
reload
.
status_page_setting
.
masked_aws_secret_key
}
}
end
it
'returns a validation error'
do
expect
(
result
[
:status
]).
to
eq
(
:error
)
end
end
end
context
'without an existing setting'
do
it
'creates a setting'
do
expect
(
project
.
status_page_setting
).
to
be_nil
expect
(
result
[
:status
]).
to
eq
(
:success
)
expect
(
project
.
reload
.
status_page_setting
.
aws_s3_bucket_name
)
.
to
eq
(
'test'
)
end
end
end
end
end
end
spec/lib/gitlab/import_export/all_models.yml
View file @
867151ac
...
...
@@ -466,6 +466,7 @@ project:
-
container_expiration_policy
-
resource_groups
-
autoclose_referenced_issues
-
status_page_setting
award_emoji
:
-
awardable
-
user
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment