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
621b4eaf
Commit
621b4eaf
authored
Sep 02, 2016
by
James Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixing a couple of bugs and lots of refactoring of the export file spec
parent
13a97747
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
259 additions
and
234 deletions
+259
-234
spec/features/projects/import_export/export_file_spec.rb
spec/features/projects/import_export/export_file_spec.rb
+12
-3
spec/lib/gitlab/import_export/all_models.json
spec/lib/gitlab/import_export/all_models.json
+0
-196
spec/lib/gitlab/import_export/all_models.yml
spec/lib/gitlab/import_export/all_models.yml
+175
-0
spec/lib/gitlab/import_export/attribute_configuration_spec.rb
.../lib/gitlab/import_export/attribute_configuration_spec.rb
+2
-10
spec/lib/gitlab/import_export/model_configuration_spec.rb
spec/lib/gitlab/import_export/model_configuration_spec.rb
+9
-8
spec/support/import_export/configuration_helper.rb
spec/support/import_export/configuration_helper.rb
+10
-0
spec/support/import_export/export_file_helper.rb
spec/support/import_export/export_file_helper.rb
+51
-17
No files found.
spec/features/projects/import_export/export_file_spec.rb
View file @
621b4eaf
require
'spec_helper'
require
'spec_helper'
# Integration test that exports a file using the Import/EXport feature
# It looks up for any sensitive word inside the JSON, so if a sensitive word is found
# we''l have to either include it adding the model containing it to the +safe_list+
# or make sure the attribute is blacklisted in the +import_export.yml+ configuration
feature
'project export'
,
feature:
true
,
js:
true
do
feature
'project export'
,
feature:
true
,
js:
true
do
include
Select2Helper
include
Select2Helper
include
ExportFileHelper
include
ExportFileHelper
let
(
:user
)
{
create
(
:admin
)
}
let
(
:user
)
{
create
(
:admin
)
}
let
(
:export_path
)
{
"
#{
Dir
::
tmpdir
}
/import_file_spec"
}
let
(
:export_path
)
{
"
#{
Dir
::
tmpdir
}
/import_file_spec"
}
let
(
:config_hash
)
{
YAML
.
load_file
(
Gitlab
::
ImportExport
.
config_file
).
deep_stringify_keys
}
let
(
:sensitive_words
)
{
%w[pass secret token key]
}
let
(
:sensitive_words
)
{
%w[pass secret token key]
}
let
(
:safe_
models
)
do
let
(
:safe_
list
)
do
{
{
token:
[
ProjectHook
,
Ci
::
Trigger
]
token:
[
ProjectHook
,
Ci
::
Trigger
],
key:
[
Project
,
Ci
::
Variable
,
:yaml_variables
]
}
}
end
end
let
(
:safe_hashes
)
{
{
yaml_variables:
%w[key value public]
}
}
let
(
:project
)
{
setup_project
}
let
(
:project
)
{
setup_project
}
...
@@ -49,7 +56,9 @@ feature 'project export', feature: true, js: true do
...
@@ -49,7 +56,9 @@ feature 'project export', feature: true, js: true do
project_hash
=
JSON
.
parse
(
IO
.
read
(
project_json_path
))
project_hash
=
JSON
.
parse
(
IO
.
read
(
project_json_path
))
sensitive_words
.
each
do
|
sensitive_word
|
sensitive_words
.
each
do
|
sensitive_word
|
expect
(
has_sensitive_attributes?
(
sensitive_word
,
project_hash
)).
to
be
false
found
=
find_sensitive_attributes
(
sensitive_word
,
project_hash
)
expect
(
found
).
to
be_nil
,
"Found a new sensitive word <
#{
found
.
try
(
:key_found
)
}
>, which is part of the hash
#{
found
.
try
(
:parent
)
}
"
end
end
end
end
end
end
...
...
spec/lib/gitlab/import_export/all_models.json
deleted
100644 → 0
View file @
13a97747
{
"issues"
:
[
"subscriptions"
,
"award_emoji"
,
"author"
,
"assignee"
,
"updated_by"
,
"milestone"
,
"notes"
,
"label_links"
,
"labels"
,
"todos"
,
"user_agent_detail"
,
"project"
,
"moved_to"
,
"events"
],
"events"
:
[
"author"
,
"project"
,
"target"
],
"notes"
:
[
"award_emoji"
,
"project"
,
"noteable"
,
"author"
,
"updated_by"
,
"resolved_by"
,
"todos"
,
"events"
],
"label_links"
:
[
"target"
,
"label"
],
"label"
:
[
"subscriptions"
,
"project"
,
"lists"
,
"label_links"
,
"issues"
,
"merge_requests"
],
"milestone"
:
[
"project"
,
"issues"
,
"labels"
,
"merge_requests"
,
"participants"
,
"events"
],
"snippets"
:
[
"author"
,
"project"
,
"notes"
],
"releases"
:
[
"project"
],
"project_members"
:
[
"created_by"
,
"user"
,
"source"
,
"project"
],
"merge_requests"
:
[
"subscriptions"
,
"award_emoji"
,
"author"
,
"assignee"
,
"updated_by"
,
"milestone"
,
"notes"
,
"label_links"
,
"labels"
,
"todos"
,
"target_project"
,
"source_project"
,
"merge_user"
,
"merge_request_diffs"
,
"merge_request_diff"
,
"events"
],
"merge_request_diff"
:
[
"merge_request"
],
"pipelines"
:
[
"project"
,
"user"
,
"statuses"
,
"builds"
,
"trigger_requests"
],
"statuses"
:
[
"project"
,
"pipeline"
,
"user"
],
"variables"
:
[
"project"
],
"triggers"
:
[
"project"
,
"trigger_requests"
],
"deploy_keys"
:
[
"user"
,
"deploy_keys_projects"
,
"projects"
],
"services"
:
[
"project"
,
"service_hook"
],
"hooks"
:
[
"project"
],
"protected_branches"
:
[
"project"
,
"merge_access_levels"
,
"push_access_levels"
],
"project"
:
[
"taggings"
,
"base_tags"
,
"tag_taggings"
,
"tags"
,
"creator"
,
"group"
,
"namespace"
,
"board"
,
"last_event"
,
"services"
,
"campfire_service"
,
"drone_ci_service"
,
"emails_on_push_service"
,
"builds_email_service"
,
"irker_service"
,
"pivotaltracker_service"
,
"hipchat_service"
,
"flowdock_service"
,
"assembla_service"
,
"asana_service"
,
"gemnasium_service"
,
"slack_service"
,
"buildkite_service"
,
"bamboo_service"
,
"teamcity_service"
,
"pushover_service"
,
"jira_service"
,
"redmine_service"
,
"custom_issue_tracker_service"
,
"bugzilla_service"
,
"gitlab_issue_tracker_service"
,
"external_wiki_service"
,
"forked_project_link"
,
"forked_from_project"
,
"forked_project_links"
,
"forks"
,
"merge_requests"
,
"fork_merge_requests"
,
"issues"
,
"labels"
,
"events"
,
"milestones"
,
"notes"
,
"snippets"
,
"hooks"
,
"protected_branches"
,
"project_members"
,
"users"
,
"requesters"
,
"deploy_keys_projects"
,
"deploy_keys"
,
"users_star_projects"
,
"starrers"
,
"releases"
,
"lfs_objects_projects"
,
"lfs_objects"
,
"project_group_links"
,
"invited_groups"
,
"todos"
,
"notification_settings"
,
"import_data"
,
"commit_statuses"
,
"pipelines"
,
"builds"
,
"runner_projects"
,
"runners"
,
"variables"
,
"triggers"
,
"environments"
,
"deployments"
]
}
\ No newline at end of file
spec/lib/gitlab/import_export/all_models.yml
0 → 100644
View file @
621b4eaf
---
issues
:
-
subscriptions
-
award_emoji
-
author
-
assignee
-
updated_by
-
milestone
-
notes
-
label_links
-
labels
-
todos
-
user_agent_detail
-
project
-
moved_to
-
events
events
:
-
author
-
project
-
target
notes
:
-
award_emoji
-
project
-
noteable
-
author
-
updated_by
-
resolved_by
-
todos
-
events
label_links
:
-
target
-
label
label
:
-
subscriptions
-
project
-
lists
-
label_links
-
issues
-
merge_requests
milestone
:
-
project
-
issues
-
labels
-
merge_requests
-
participants
-
events
snippets
:
-
author
-
project
-
notes
releases
:
-
project
project_members
:
-
created_by
-
user
-
source
-
project
merge_requests
:
-
subscriptions
-
award_emoji
-
author
-
assignee
-
updated_by
-
milestone
-
notes
-
label_links
-
labels
-
todos
-
target_project
-
source_project
-
merge_user
-
merge_request_diffs
-
merge_request_diff
-
events
merge_request_diff
:
-
merge_request
pipelines
:
-
project
-
user
-
statuses
-
builds
-
trigger_requests
statuses
:
-
project
-
pipeline
-
user
variables
:
-
project
triggers
:
-
project
-
trigger_requests
deploy_keys
:
-
user
-
deploy_keys_projects
-
projects
services
:
-
project
-
service_hook
hooks
:
-
project
protected_branches
:
-
project
-
merge_access_levels
-
push_access_levels
project
:
-
taggings
-
base_tags
-
tag_taggings
-
tags
-
creator
-
group
-
namespace
-
board
-
last_event
-
services
-
campfire_service
-
drone_ci_service
-
emails_on_push_service
-
builds_email_service
-
irker_service
-
pivotaltracker_service
-
hipchat_service
-
flowdock_service
-
assembla_service
-
asana_service
-
gemnasium_service
-
slack_service
-
buildkite_service
-
bamboo_service
-
teamcity_service
-
pushover_service
-
jira_service
-
redmine_service
-
custom_issue_tracker_service
-
bugzilla_service
-
gitlab_issue_tracker_service
-
external_wiki_service
-
forked_project_link
-
forked_from_project
-
forked_project_links
-
forks
-
merge_requests
-
fork_merge_requests
-
issues
-
labels
-
events
-
milestones
-
notes
-
snippets
-
hooks
-
protected_branches
-
project_members
-
users
-
requesters
-
deploy_keys_projects
-
deploy_keys
-
users_star_projects
-
starrers
-
releases
-
lfs_objects_projects
-
lfs_objects
-
project_group_links
-
invited_groups
-
todos
-
notification_settings
-
import_data
-
commit_statuses
-
pipelines
-
builds
-
runner_projects
-
runners
-
variables
-
triggers
-
environments
-
deployments
spec/lib/gitlab/import_export/attribute_configuration_spec.rb
View file @
621b4eaf
require
'spec_helper'
require
'spec_helper'
# Part of the Import/Export feature security testing
# Checks whether there are new attributes in models that are currently being exported as part of the
# Checks whether there are new attributes in models that are currently being exported as part of the
# project Import/Export feature.
# project Import/Export feature.
# If there are new attributes, these will have to either be added to this spec in case we want them
# If there are new attributes, these will have to either be added to this spec in case we want them
...
@@ -73,16 +75,6 @@ describe 'Attribute configuration', lib: true do
...
@@ -73,16 +75,6 @@ describe 'Attribute configuration', lib: true do
MSG
MSG
end
end
def
parsed_attributes
(
relation_name
,
attributes
)
excluded_attributes
=
config_hash
[
'excluded_attributes'
][
relation_name
]
included_attributes
=
config_hash
[
'included_attributes'
][
relation_name
]
attributes
=
attributes
-
JSON
[
excluded_attributes
.
to_json
]
if
excluded_attributes
attributes
=
attributes
&
JSON
[
included_attributes
.
to_json
]
if
included_attributes
attributes
end
class
Author
<
User
class
Author
<
User
end
end
end
end
spec/lib/gitlab/import_export/model_configuration_spec.rb
View file @
621b4eaf
require
'spec_helper'
require
'spec_helper'
# Part of the Import/Export feature security testing
# Finds if a new model has been added that can potentially be part of the Import/Export
# Finds if a new model has been added that can potentially be part of the Import/Export
# If it finds a new model, it will show a +failure_message+ with the options available.
# If it finds a new model, it will show a +failure_message+ with the options available.
describe
'Model configuration'
,
lib:
true
do
describe
'Model configuration'
,
lib:
true
do
...
@@ -12,12 +13,12 @@ describe 'Model configuration', lib: true do
...
@@ -12,12 +13,12 @@ describe 'Model configuration', lib: true do
# Remove duplicated or add missing models
# Remove duplicated or add missing models
# - project is not part of the tree, so it has to be added manually.
# - project is not part of the tree, so it has to be added manually.
# - milestone, labels have both singular and plural versions in the tree, so remove the duplicates.
# - milestone, labels have both singular and plural versions in the tree, so remove the duplicates.
# - User, Author... Models we do
n
not care about for checking relations
# - User, Author... Models we do not care about for checking relations
names
.
flatten
.
uniq
-
[
'milestones'
,
'labels'
,
'user'
,
'author'
]
+
[
'project'
]
names
.
flatten
.
uniq
-
[
'milestones'
,
'labels'
,
'user'
,
'author'
]
+
[
'project'
]
end
end
let
(
:all_models_
json
)
{
'spec/lib/gitlab/import_export/all_models.json
'
}
let
(
:all_models_
yml
)
{
'spec/lib/gitlab/import_export/all_models.yml
'
}
let
(
:all_models
)
{
JSON
.
parse
(
File
.
read
(
all_models_json
)
)
}
let
(
:all_models
)
{
YAML
.
load_file
(
all_models_yml
)
}
let
(
:current_models
)
{
setup_models
}
let
(
:current_models
)
{
setup_models
}
it
'has no new models'
do
it
'has no new models'
do
...
@@ -43,15 +44,15 @@ describe 'Model configuration', lib: true do
...
@@ -43,15 +44,15 @@ describe 'Model configuration', lib: true do
all_models_hash
all_models_hash
end
end
def
failure_message
(
relation
_name
,
new_models
)
def
failure_message
(
parent_model
_name
,
new_models
)
<<-
MSG
<<-
MSG
New model(s) <
#{
new_models
.
join
(
','
)
}
> have been added, related to
#{
relation
_name
}
, which is exported by
New model(s) <
#{
new_models
.
join
(
','
)
}
> have been added, related to
#{
parent_model
_name
}
, which is exported by
the Import/Export feature.
the Import/Export feature.
If you don't think this should be exported, please add it to MODELS_JSON, inside the
#{
relation
_name
}
hash.
If you don't think this should be exported, please add it to MODELS_JSON, inside the
#{
parent_model
_name
}
hash.
If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG.
If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG
and to MODELS_JSON
.
MODELS_JSON:
#{
File
.
expand_path
(
all_models_
json
)
}
MODELS_JSON:
#{
File
.
expand_path
(
all_models_
yml
)
}
IMPORT_EXPORT_CONFIG:
#{
Gitlab
::
ImportExport
.
config_file
}
IMPORT_EXPORT_CONFIG:
#{
Gitlab
::
ImportExport
.
config_file
}
MSG
MSG
end
end
...
...
spec/support/import_export/configuration_helper.rb
View file @
621b4eaf
...
@@ -12,4 +12,14 @@ module ConfigurationHelper
...
@@ -12,4 +12,14 @@ module ConfigurationHelper
relation_name
=
Gitlab
::
ImportExport
::
RelationFactory
::
OVERRIDES
[
relation_name
.
to_sym
]
||
relation_name
relation_name
=
Gitlab
::
ImportExport
::
RelationFactory
::
OVERRIDES
[
relation_name
.
to_sym
]
||
relation_name
relation_name
.
to_s
.
classify
.
constantize
relation_name
.
to_s
.
classify
.
constantize
end
end
def
parsed_attributes
(
relation_name
,
attributes
)
excluded_attributes
=
config_hash
[
'excluded_attributes'
][
relation_name
]
included_attributes
=
config_hash
[
'included_attributes'
][
relation_name
]
attributes
=
attributes
-
JSON
[
excluded_attributes
.
to_json
]
if
excluded_attributes
attributes
=
attributes
&
JSON
[
included_attributes
.
to_json
]
if
included_attributes
attributes
end
end
end
spec/support/import_export/export_file_helper.rb
View file @
621b4eaf
module
ExportFileHelper
module
ExportFileHelper
include
ConfigurationHelper
ObjectWithParent
=
Struct
.
new
(
:object
,
:parent
,
:key_found
)
def
setup_project
def
setup_project
project
=
create
(
:project
,
:public
)
project
=
create
(
:project
,
:public
)
...
@@ -54,48 +58,78 @@ module ExportFileHelper
...
@@ -54,48 +58,78 @@ module ExportFileHelper
# Recursively finds key/values including +key+ as part of the key, inside a nested hash
# Recursively finds key/values including +key+ as part of the key, inside a nested hash
def
deep_find_with_parent
(
sensitive_key_word
,
object
,
found
=
nil
)
def
deep_find_with_parent
(
sensitive_key_word
,
object
,
found
=
nil
)
sensitive_key_found
=
object_contains_key?
(
object
,
sensitive_key_word
)
# Returns the parent object and the object found containing a sensitive word as part of the key
# Returns the parent object and the object found containing a sensitive word as part of the key
if
object_contains_key?
(
object
,
sensitive_key_word
)
if
sensitive_key_found
&&
object
[
sensitive_key_found
]
[
object
[
sensitive_key_word
],
object
]
if
object
[
sensitive_key_word
]
ObjectWithParent
.
new
(
object
[
sensitive_key_found
],
object
,
sensitive_key_found
)
elsif
object
.
is_a?
(
Enumerable
)
elsif
object
.
is_a?
(
Enumerable
)
# Recursively lookup for keys containing sensitive words in a Hash or Array
# Recursively lookup for keys containing sensitive words in a Hash or Array
object
.
find
{
|*
hash_or_array
|
found
,
object
=
deep_find_with_parent
(
sensitive_key_word
,
hash_or_array
.
last
,
found
)
}
object_with_parent
=
nil
[
found
,
object
]
if
found
object
.
find
do
|*
hash_or_array
|
object_with_parent
=
deep_find_with_parent
(
sensitive_key_word
,
hash_or_array
.
last
,
found
)
end
object_with_parent
end
end
end
end
# Return true if the hash has a key containing a sensitive word
# Return true if the hash has a key containing a sensitive word
def
object_contains_key?
(
object
,
sensitive_key_word
)
def
object_contains_key?
(
object
,
sensitive_key_word
)
object
.
is_a?
(
Hash
)
&&
object
.
keys
.
any?
{
|
key
|
key
.
include?
(
sensitive_key_word
)
}
return
false
unless
object
.
is_a?
(
Hash
)
object
.
keys
.
find
{
|
key
|
key
.
include?
(
sensitive_key_word
)
}
end
end
# Returns true if a sensitive word is found inside a hash, excluding safe hashes
# Returns the offended ObjectWithParent object if a sensitive word is found inside a hash,
def
has_sensitive_attributes?
(
sensitive_word
,
project_hash
)
# excluding the whitelisted safe hashes.
def
find_sensitive_attributes
(
sensitive_word
,
project_hash
)
loop
do
loop
do
object
,
parent
=
deep_find_with_parent
(
sensitive_word
,
project_hash
)
object_with_parent
=
deep_find_with_parent
(
sensitive_word
,
project_hash
)
return
nil
unless
object_with_parent
&&
object_with_parent
.
object
if
object
&&
is_safe_hash?
(
parent
,
sensitive_word
)
if
is_safe_hash?
(
object_with_parent
.
parent
,
sensitive_word
)
# It's in the safe list, remove hash and keep looking
# It's in the safe list, remove hash and keep looking
parent
.
delete
(
object
)
object_with_parent
.
parent
.
delete
(
object_with_parent
.
key_found
)
elsif
object
return
true
else
else
return
false
return
object_with_parent
end
end
nil
end
end
end
end
# Returns true if it's one of the excluded models in +safe_
models
+
# Returns true if it's one of the excluded models in +safe_
list
+
def
is_safe_hash?
(
parent
,
sensitive_word
)
def
is_safe_hash?
(
parent
,
sensitive_word
)
return
false
unless
parent
return
false
unless
parent
&&
safe_list
[
sensitive_word
.
to_sym
]
# Extra attributes that appear in a model but not in the exported hash.
# Extra attributes that appear in a model but not in the exported hash.
excluded_attributes
=
[
'type'
]
excluded_attributes
=
[
'type'
]
safe_models
[
sensitive_word
.
to_sym
].
each
do
|
safe_model
|
safe_list
[
sensitive_word
.
to_sym
].
each
do
|
model
|
return
true
if
(
safe_model
.
attribute_names
-
parent
.
keys
-
excluded_attributes
).
empty?
# Check whether this is a hash attribute inside a model
if
model
.
is_a?
(
Symbol
)
return
true
if
(
safe_hashes
[
model
]
-
parent
.
keys
).
empty?
else
return
true
if
safe_model?
(
model
,
excluded_attributes
,
parent
)
end
end
end
false
false
end
end
def
associations_for
(
safe_model
)
safe_model
.
reflect_on_all_associations
.
map
{
|
assoc
|
assoc
.
name
.
to_s
}
end
# Compares model attributes with those those found in the hash
# and returns true if there is a match, ignoring some excluded attributes.
def
safe_model?
(
model
,
excluded_attributes
,
parent
)
excluded_attributes
+=
associations_for
(
model
)
parsed_model_attributes
=
parsed_attributes
(
model
.
name
.
underscore
,
model
.
attribute_names
)
(
parsed_model_attributes
-
parent
.
keys
-
excluded_attributes
).
empty?
end
end
end
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