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
632c2939
Commit
632c2939
authored
Jan 22, 2017
by
Grzegorz Bizon
Committed by
Rémy Coutable
Jan 23, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Merge branch 'revert-
9cac0317
' into 'master'
This reverts commit
c2093486
, reversing changes made to
4b7ec44b
.
parent
6c65f7a7
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
141 additions
and
104 deletions
+141
-104
app/models/application_setting.rb
app/models/application_setting.rb
+44
-40
lib/gitlab/current_settings.rb
lib/gitlab/current_settings.rb
+13
-31
lib/gitlab/github_import/project_creator.rb
lib/gitlab/github_import/project_creator.rb
+3
-1
spec/controllers/health_check_controller_spec.rb
spec/controllers/health_check_controller_spec.rb
+6
-0
spec/features/admin/admin_disables_git_access_protocol_spec.rb
...features/admin/admin_disables_git_access_protocol_spec.rb
+3
-0
spec/features/admin/admin_health_check_spec.rb
spec/features/admin/admin_health_check_spec.rb
+6
-3
spec/features/admin/admin_runners_spec.rb
spec/features/admin/admin_runners_spec.rb
+3
-0
spec/features/admin/admin_settings_spec.rb
spec/features/admin/admin_settings_spec.rb
+4
-1
spec/features/admin/admin_uses_repository_checks_spec.rb
spec/features/admin/admin_uses_repository_checks_spec.rb
+7
-2
spec/lib/gitlab/current_settings_spec.rb
spec/lib/gitlab/current_settings_spec.rb
+48
-20
spec/requests/api/internal_spec.rb
spec/requests/api/internal_spec.rb
+3
-6
spec/spec_helper.rb
spec/spec_helper.rb
+1
-0
No files found.
app/models/application_setting.rb
View file @
632c2939
...
@@ -13,6 +13,49 @@ class ApplicationSetting < ActiveRecord::Base
...
@@ -13,6 +13,49 @@ class ApplicationSetting < ActiveRecord::Base
[
\r\n
] # any number of newline characters
[
\r\n
] # any number of newline characters
}x
}x
DEFAULTS_CE
=
{
after_sign_up_text:
nil
,
akismet_enabled:
false
,
container_registry_token_expire_delay:
5
,
default_branch_protection:
Settings
.
gitlab
[
'default_branch_protection'
],
default_project_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
default_projects_limit:
Settings
.
gitlab
[
'default_projects_limit'
],
default_snippet_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
disabled_oauth_sign_in_sources:
[],
domain_whitelist:
Settings
.
gitlab
[
'domain_whitelist'
],
gravatar_enabled:
Settings
.
gravatar
[
'enabled'
],
help_page_text:
nil
,
housekeeping_bitmaps_enabled:
true
,
housekeeping_enabled:
true
,
housekeeping_full_repack_period:
50
,
housekeeping_gc_period:
200
,
housekeeping_incremental_repack_period:
10
,
import_sources:
Gitlab
::
ImportSources
.
values
,
koding_enabled:
false
,
koding_url:
nil
,
max_artifacts_size:
Settings
.
artifacts
[
'max_size'
],
max_attachment_size:
Settings
.
gitlab
[
'max_attachment_size'
],
plantuml_enabled:
false
,
plantuml_url:
nil
,
recaptcha_enabled:
false
,
repository_checks_enabled:
true
,
repository_storages:
[
'default'
],
require_two_factor_authentication:
false
,
restricted_visibility_levels:
Settings
.
gitlab
[
'restricted_visibility_levels'
],
session_expire_delay:
Settings
.
gitlab
[
'session_expire_delay'
],
send_user_confirmation_email:
false
,
shared_runners_enabled:
Settings
.
gitlab_ci
[
'shared_runners_enabled'
],
shared_runners_text:
nil
,
sidekiq_throttling_enabled:
false
,
sign_in_text:
nil
,
signin_enabled:
Settings
.
gitlab
[
'signin_enabled'
],
signup_enabled:
Settings
.
gitlab
[
'signup_enabled'
],
two_factor_grace_period:
48
,
user_default_external:
false
}
DEFAULTS
=
DEFAULTS_CE
serialize
:restricted_visibility_levels
serialize
:restricted_visibility_levels
serialize
:import_sources
serialize
:import_sources
serialize
:disabled_oauth_sign_in_sources
,
Array
serialize
:disabled_oauth_sign_in_sources
,
Array
...
@@ -163,46 +206,7 @@ class ApplicationSetting < ActiveRecord::Base
...
@@ -163,46 +206,7 @@ class ApplicationSetting < ActiveRecord::Base
end
end
def
self
.
create_from_defaults
def
self
.
create_from_defaults
create
(
create
(
DEFAULTS
)
default_projects_limit:
Settings
.
gitlab
[
'default_projects_limit'
],
default_branch_protection:
Settings
.
gitlab
[
'default_branch_protection'
],
signup_enabled:
Settings
.
gitlab
[
'signup_enabled'
],
signin_enabled:
Settings
.
gitlab
[
'signin_enabled'
],
gravatar_enabled:
Settings
.
gravatar
[
'enabled'
],
sign_in_text:
nil
,
after_sign_up_text:
nil
,
help_page_text:
nil
,
shared_runners_text:
nil
,
restricted_visibility_levels:
Settings
.
gitlab
[
'restricted_visibility_levels'
],
max_attachment_size:
Settings
.
gitlab
[
'max_attachment_size'
],
session_expire_delay:
Settings
.
gitlab
[
'session_expire_delay'
],
default_project_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
default_snippet_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
domain_whitelist:
Settings
.
gitlab
[
'domain_whitelist'
],
import_sources:
Gitlab
::
ImportSources
.
values
,
shared_runners_enabled:
Settings
.
gitlab_ci
[
'shared_runners_enabled'
],
max_artifacts_size:
Settings
.
artifacts
[
'max_size'
],
require_two_factor_authentication:
false
,
two_factor_grace_period:
48
,
recaptcha_enabled:
false
,
akismet_enabled:
false
,
koding_enabled:
false
,
koding_url:
nil
,
plantuml_enabled:
false
,
plantuml_url:
nil
,
repository_checks_enabled:
true
,
disabled_oauth_sign_in_sources:
[],
send_user_confirmation_email:
false
,
container_registry_token_expire_delay:
5
,
repository_storages:
[
'default'
],
user_default_external:
false
,
sidekiq_throttling_enabled:
false
,
housekeeping_enabled:
true
,
housekeeping_bitmaps_enabled:
true
,
housekeeping_incremental_repack_period:
10
,
housekeeping_full_repack_period:
50
,
housekeeping_gc_period:
200
,
)
end
end
def
home_page_url_column_exist
def
home_page_url_column_exist
...
...
lib/gitlab/current_settings.rb
View file @
632c2939
...
@@ -9,7 +9,9 @@ module Gitlab
...
@@ -9,7 +9,9 @@ module Gitlab
end
end
def
ensure_application_settings!
def
ensure_application_settings!
if
connect_to_db?
return
fake_application_settings
unless
connect_to_db?
unless
ENV
[
'IN_MEMORY_APPLICATION_SETTINGS'
]
==
'true'
begin
begin
settings
=
::
ApplicationSetting
.
current
settings
=
::
ApplicationSetting
.
current
# In case Redis isn't running or the Redis UNIX socket file is not available
# In case Redis isn't running or the Redis UNIX socket file is not available
...
@@ -20,43 +22,23 @@ module Gitlab
...
@@ -20,43 +22,23 @@ module Gitlab
settings
||=
::
ApplicationSetting
.
create_from_defaults
unless
ActiveRecord
::
Migrator
.
needs_migration?
settings
||=
::
ApplicationSetting
.
create_from_defaults
unless
ActiveRecord
::
Migrator
.
needs_migration?
end
end
settings
||
fake
_application_settings
settings
||
in_memory
_application_settings
end
end
def
sidekiq_throttling_enabled?
def
sidekiq_throttling_enabled?
current_application_settings
.
sidekiq_throttling_enabled?
current_application_settings
.
sidekiq_throttling_enabled?
end
end
def
in_memory_application_settings
@in_memory_application_settings
||=
ApplicationSetting
.
new
(
ApplicationSetting
::
DEFAULTS
)
# In case migrations the application_settings table is not created yet,
# we fallback to a simple OpenStruct
rescue
ActiveRecord
::
StatementInvalid
fake_application_settings
end
def
fake_application_settings
def
fake_application_settings
OpenStruct
.
new
(
OpenStruct
.
new
(
ApplicationSetting
::
DEFAULTS
)
default_projects_limit:
Settings
.
gitlab
[
'default_projects_limit'
],
default_branch_protection:
Settings
.
gitlab
[
'default_branch_protection'
],
signup_enabled:
Settings
.
gitlab
[
'signup_enabled'
],
signin_enabled:
Settings
.
gitlab
[
'signin_enabled'
],
gravatar_enabled:
Settings
.
gravatar
[
'enabled'
],
koding_enabled:
false
,
plantuml_enabled:
false
,
sign_in_text:
nil
,
after_sign_up_text:
nil
,
help_page_text:
nil
,
shared_runners_text:
nil
,
restricted_visibility_levels:
Settings
.
gitlab
[
'restricted_visibility_levels'
],
max_attachment_size:
Settings
.
gitlab
[
'max_attachment_size'
],
session_expire_delay:
Settings
.
gitlab
[
'session_expire_delay'
],
default_project_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
default_snippet_visibility:
Settings
.
gitlab
.
default_projects_features
[
'visibility_level'
],
domain_whitelist:
Settings
.
gitlab
[
'domain_whitelist'
],
import_sources:
%w[gitea github bitbucket gitlab google_code fogbugz git gitlab_project]
,
shared_runners_enabled:
Settings
.
gitlab_ci
[
'shared_runners_enabled'
],
max_artifacts_size:
Settings
.
artifacts
[
'max_size'
],
require_two_factor_authentication:
false
,
two_factor_grace_period:
48
,
akismet_enabled:
false
,
repository_checks_enabled:
true
,
container_registry_token_expire_delay:
5
,
user_default_external:
false
,
sidekiq_throttling_enabled:
false
,
)
end
end
private
private
...
...
lib/gitlab/github_import/project_creator.rb
View file @
632c2939
module
Gitlab
module
Gitlab
module
GithubImport
module
GithubImport
class
ProjectCreator
class
ProjectCreator
include
Gitlab
::
CurrentSettings
attr_reader
:repo
,
:name
,
:namespace
,
:current_user
,
:session_data
,
:type
attr_reader
:repo
,
:name
,
:namespace
,
:current_user
,
:session_data
,
:type
def
initialize
(
repo
,
name
,
namespace
,
current_user
,
session_data
,
type:
'github'
)
def
initialize
(
repo
,
name
,
namespace
,
current_user
,
session_data
,
type:
'github'
)
...
@@ -34,7 +36,7 @@ module Gitlab
...
@@ -34,7 +36,7 @@ module Gitlab
end
end
def
visibility_level
def
visibility_level
repo
.
private
?
Gitlab
::
VisibilityLevel
::
PRIVATE
:
ApplicationSetting
.
current
.
default_project_visibility
repo
.
private
?
Gitlab
::
VisibilityLevel
::
PRIVATE
:
current_application_settings
.
default_project_visibility
end
end
#
#
...
...
spec/controllers/health_check_controller_spec.rb
View file @
632c2939
require
'spec_helper'
require
'spec_helper'
describe
HealthCheckController
do
describe
HealthCheckController
do
include
StubENV
let
(
:token
)
{
current_application_settings
.
health_check_access_token
}
let
(
:token
)
{
current_application_settings
.
health_check_access_token
}
let
(
:json_response
)
{
JSON
.
parse
(
response
.
body
)
}
let
(
:json_response
)
{
JSON
.
parse
(
response
.
body
)
}
let
(
:xml_response
)
{
Hash
.
from_xml
(
response
.
body
)[
'hash'
]
}
let
(
:xml_response
)
{
Hash
.
from_xml
(
response
.
body
)[
'hash'
]
}
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
end
describe
'GET #index'
do
describe
'GET #index'
do
context
'when services are up but NO access token'
do
context
'when services are up but NO access token'
do
it
'returns a not found page'
do
it
'returns a not found page'
do
...
...
spec/features/admin/admin_disables_git_access_protocol_spec.rb
View file @
632c2939
require
'rails_helper'
require
'rails_helper'
feature
'Admin disables Git access protocol'
,
feature:
true
do
feature
'Admin disables Git access protocol'
,
feature:
true
do
include
StubENV
let
(
:project
)
{
create
(
:empty_project
,
:empty_repo
)
}
let
(
:project
)
{
create
(
:empty_project
,
:empty_repo
)
}
let
(
:admin
)
{
create
(
:admin
)
}
let
(
:admin
)
{
create
(
:admin
)
}
background
do
background
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
login_as
(
admin
)
login_as
(
admin
)
end
end
...
...
spec/features/admin/admin_health_check_spec.rb
View file @
632c2939
require
'spec_helper'
require
'spec_helper'
feature
"Admin Health Check"
,
feature:
true
do
feature
"Admin Health Check"
,
feature:
true
do
include
StubENV
include
WaitForAjax
include
WaitForAjax
before
do
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
login_as
:admin
login_as
:admin
end
end
...
@@ -12,11 +14,12 @@ feature "Admin Health Check", feature: true do
...
@@ -12,11 +14,12 @@ feature "Admin Health Check", feature: true do
visit
admin_health_check_path
visit
admin_health_check_path
end
end
it
{
page
.
has_text?
'Health Check'
}
it
{
page
.
has_text?
'Health information can be retrieved'
}
it
'has a health check access token'
do
it
'has a health check access token'
do
page
.
has_text?
'Health Check'
page
.
has_text?
'Health information can be retrieved'
token
=
current_application_settings
.
health_check_access_token
token
=
current_application_settings
.
health_check_access_token
expect
(
page
).
to
have_content
(
"Access token is
#{
token
}
"
)
expect
(
page
).
to
have_content
(
"Access token is
#{
token
}
"
)
expect
(
page
).
to
have_selector
(
'#health-check-token'
,
text:
token
)
expect
(
page
).
to
have_selector
(
'#health-check-token'
,
text:
token
)
end
end
...
...
spec/features/admin/admin_runners_spec.rb
View file @
632c2939
require
'spec_helper'
require
'spec_helper'
describe
"Admin Runners"
do
describe
"Admin Runners"
do
include
StubENV
before
do
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
login_as
:admin
login_as
:admin
end
end
...
...
spec/features/admin/admin_settings_spec.rb
View file @
632c2939
require
'spec_helper'
require
'spec_helper'
feature
'Admin updates settings'
,
feature:
true
do
feature
'Admin updates settings'
,
feature:
true
do
before
(
:each
)
do
include
StubENV
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
login_as
:admin
login_as
:admin
visit
admin_application_settings_path
visit
admin_application_settings_path
end
end
...
...
spec/features/admin/admin_uses_repository_checks_spec.rb
View file @
632c2939
require
'rails_helper'
require
'rails_helper'
feature
'Admin uses repository checks'
,
feature:
true
do
feature
'Admin uses repository checks'
,
feature:
true
do
before
{
login_as
:admin
}
include
StubENV
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
login_as
:admin
end
scenario
'to trigger a single check'
do
scenario
'to trigger a single check'
do
project
=
create
(
:empty_project
)
project
=
create
(
:empty_project
)
...
@@ -29,7 +34,7 @@ feature 'Admin uses repository checks', feature: true do
...
@@ -29,7 +34,7 @@ feature 'Admin uses repository checks', feature: true do
scenario
'to clear all repository checks'
,
js:
true
do
scenario
'to clear all repository checks'
,
js:
true
do
visit
admin_application_settings_path
visit
admin_application_settings_path
expect
(
RepositoryCheck
::
ClearWorker
).
to
receive
(
:perform_async
)
expect
(
RepositoryCheck
::
ClearWorker
).
to
receive
(
:perform_async
)
click_link
'Clear all repository checks'
click_link
'Clear all repository checks'
...
...
spec/lib/gitlab/current_settings_spec.rb
View file @
632c2939
require
'spec_helper'
require
'spec_helper'
describe
Gitlab
::
CurrentSettings
do
describe
Gitlab
::
CurrentSettings
do
include
StubENV
before
do
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'false'
)
end
describe
'#current_application_settings'
do
describe
'#current_application_settings'
do
it
'attempts to use cached values first
'
do
context
'with DB available
'
do
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
true
)
before
do
expect
(
ApplicationSetting
).
to
receive
(
:current
).
and_return
(
::
ApplicationSetting
.
create_from_defaults
)
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
true
)
e
xpect
(
ApplicationSetting
).
not_to
receive
(
:last
)
e
nd
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
it
'attempts to use cached values first'
do
end
expect
(
ApplicationSetting
).
to
receive
(
:current
)
expect
(
ApplicationSetting
).
not_to
receive
(
:last
)
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
end
it
'does not attempt to connect to DB or Redis'
do
it
'falls back to DB if Redis returns an empty value'
do
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
false
)
expect
(
ApplicationSetting
).
to
receive
(
:last
).
and_call_original
expect
(
ApplicationSetting
).
not_to
receive
(
:current
)
expect
(
ApplicationSetting
).
not_to
receive
(
:last
)
expect
(
current_application_settings
).
to
eq
fake_application_settings
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
end
it
'falls back to DB if Redis fails'
do
expect
(
ApplicationSetting
).
to
receive
(
:current
).
and_raise
(
::
Redis
::
BaseError
)
expect
(
ApplicationSetting
).
to
receive
(
:last
).
and_call_original
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
end
end
end
it
'falls back to DB if Redis returns an empty value'
do
context
'with DB unavailable'
do
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
true
)
before
do
expect
(
ApplicationSetting
).
to
receive
(
:last
).
and_call_original
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
false
)
end
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
it
'returns an in-memory ApplicationSetting object'
do
expect
(
ApplicationSetting
).
not_to
receive
(
:current
)
expect
(
ApplicationSetting
).
not_to
receive
(
:last
)
expect
(
current_application_settings
).
to
be_a
(
OpenStruct
)
end
end
end
it
'falls back to DB if Redis fails'
do
context
'when ENV["IN_MEMORY_APPLICATION_SETTINGS"] is true'
do
allow_any_instance_of
(
Gitlab
::
CurrentSettings
).
to
receive
(
:connect_to_db?
).
and_return
(
true
)
before
do
expect
(
ApplicationSetting
).
to
receive
(
:current
).
and_raise
(
::
Redis
::
BaseError
)
stub_env
(
'IN_MEMORY_APPLICATION_SETTINGS'
,
'true'
)
expect
(
ApplicationSetting
).
to
receive
(
:last
).
and_call_original
end
it
'returns an in-memory ApplicationSetting object'
do
expect
(
ApplicationSetting
).
not_to
receive
(
:current
)
expect
(
ApplicationSetting
).
not_to
receive
(
:last
)
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
expect
(
current_application_settings
).
to
be_a
(
ApplicationSetting
)
expect
(
current_application_settings
).
not_to
be_persisted
end
end
end
end
end
end
end
spec/requests/api/internal_spec.rb
View file @
632c2939
...
@@ -337,8 +337,7 @@ describe API::Internal, api: true do
...
@@ -337,8 +337,7 @@ describe API::Internal, api: true do
context
'ssh access has been disabled'
do
context
'ssh access has been disabled'
do
before
do
before
do
settings
=
::
ApplicationSetting
.
create_from_defaults
stub_application_setting
(
enabled_git_access_protocol:
'http'
)
settings
.
update_attribute
(
:enabled_git_access_protocol
,
'http'
)
end
end
it
'rejects the SSH push'
do
it
'rejects the SSH push'
do
...
@@ -360,8 +359,7 @@ describe API::Internal, api: true do
...
@@ -360,8 +359,7 @@ describe API::Internal, api: true do
context
'http access has been disabled'
do
context
'http access has been disabled'
do
before
do
before
do
settings
=
::
ApplicationSetting
.
create_from_defaults
stub_application_setting
(
enabled_git_access_protocol:
'ssh'
)
settings
.
update_attribute
(
:enabled_git_access_protocol
,
'ssh'
)
end
end
it
'rejects the HTTP push'
do
it
'rejects the HTTP push'
do
...
@@ -383,8 +381,7 @@ describe API::Internal, api: true do
...
@@ -383,8 +381,7 @@ describe API::Internal, api: true do
context
'web actions are always allowed'
do
context
'web actions are always allowed'
do
it
'allows WEB push'
do
it
'allows WEB push'
do
settings
=
::
ApplicationSetting
.
create_from_defaults
stub_application_setting
(
enabled_git_access_protocol:
'ssh'
)
settings
.
update_attribute
(
:enabled_git_access_protocol
,
'ssh'
)
project
.
team
<<
[
user
,
:developer
]
project
.
team
<<
[
user
,
:developer
]
push
(
key
,
project
,
'web'
)
push
(
key
,
project
,
'web'
)
...
...
spec/spec_helper.rb
View file @
632c2939
...
@@ -2,6 +2,7 @@ require './spec/simplecov_env'
...
@@ -2,6 +2,7 @@ require './spec/simplecov_env'
SimpleCovEnv
.
start!
SimpleCovEnv
.
start!
ENV
[
"RAILS_ENV"
]
||=
'test'
ENV
[
"RAILS_ENV"
]
||=
'test'
ENV
[
"IN_MEMORY_APPLICATION_SETTINGS"
]
=
'true'
require
File
.
expand_path
(
"../../config/environment"
,
__FILE__
)
require
File
.
expand_path
(
"../../config/environment"
,
__FILE__
)
require
'rspec/rails'
require
'rspec/rails'
...
...
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