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
d8ccc7a0
Commit
d8ccc7a0
authored
Nov 07, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
90a06a20
Changes
50
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
655 additions
and
298 deletions
+655
-298
Gemfile.lock
Gemfile.lock
+4
-4
app/assets/javascripts/repository/components/preview/index.vue
...ssets/javascripts/repository/components/preview/index.vue
+49
-0
app/assets/javascripts/repository/components/table/index.vue
app/assets/javascripts/repository/components/table/index.vue
+12
-72
app/assets/javascripts/repository/components/tree_content.vue
...assets/javascripts/repository/components/tree_content.vue
+115
-0
app/assets/javascripts/repository/graphql.js
app/assets/javascripts/repository/graphql.js
+6
-0
app/assets/javascripts/repository/pages/index.vue
app/assets/javascripts/repository/pages/index.vue
+3
-8
app/assets/javascripts/repository/pages/tree.vue
app/assets/javascripts/repository/pages/tree.vue
+3
-3
app/assets/javascripts/repository/queries/getReadme.query.graphql
...ts/javascripts/repository/queries/getReadme.query.graphql
+5
-0
app/assets/javascripts/repository/utils/readme.js
app/assets/javascripts/repository/utils/readme.js
+17
-0
app/assets/stylesheets/framework/snippets.scss
app/assets/stylesheets/framework/snippets.scss
+6
-1
app/controllers/application_controller.rb
app/controllers/application_controller.rb
+10
-12
app/controllers/concerns/confirm_email_warning.rb
app/controllers/concerns/confirm_email_warning.rb
+5
-2
app/controllers/concerns/uploads_actions.rb
app/controllers/concerns/uploads_actions.rb
+17
-0
app/controllers/uploads_controller.rb
app/controllers/uploads_controller.rb
+1
-1
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+20
-0
app/views/import/manifest/_form.html.haml
app/views/import/manifest/_form.html.haml
+1
-1
app/views/projects/_files.html.haml
app/views/projects/_files.html.haml
+0
-2
app/views/shared/snippets/_snippet.html.haml
app/views/shared/snippets/_snippet.html.haml
+3
-2
changelogs/unreleased/28350-manifest-error-file-attach.yml
changelogs/unreleased/28350-manifest-error-file-attach.yml
+5
-0
changelogs/unreleased/31964-make-snippet-list-easier-to-scan.yml
...ogs/unreleased/31964-make-snippet-list-easier-to-scan.yml
+5
-0
changelogs/unreleased/35289-remove-existence-check-in-url-constrainer.yml
...eased/35289-remove-existence-check-in-url-constrainer.yml
+5
-0
changelogs/unreleased/allow-container-scanning-to-run-offline.yml
...gs/unreleased/allow-container-scanning-to-run-offline.yml
+5
-0
changelogs/unreleased/sh-fix-bitbucket-importer-pr-state.yml
changelogs/unreleased/sh-fix-bitbucket-importer-pr-state.yml
+5
-0
config/routes/git_http.rb
config/routes/git_http.rb
+1
-1
config/routes/project.rb
config/routes/project.rb
+9
-53
lib/constraints/project_url_constrainer.rb
lib/constraints/project_url_constrainer.rb
+2
-7
lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
...ab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+7
-6
lib/gitlab/patch/draw_route.rb
lib/gitlab/patch/draw_route.rb
+1
-1
spec/controllers/application_controller_spec.rb
spec/controllers/application_controller_spec.rb
+7
-9
spec/controllers/projects/commits_controller_spec.rb
spec/controllers/projects/commits_controller_spec.rb
+2
-2
spec/controllers/projects/error_tracking_controller_spec.rb
spec/controllers/projects/error_tracking_controller_spec.rb
+1
-1
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+2
-2
spec/controllers/projects/releases_controller_spec.rb
spec/controllers/projects/releases_controller_spec.rb
+2
-2
spec/controllers/projects/tags_controller_spec.rb
spec/controllers/projects/tags_controller_spec.rb
+1
-1
spec/controllers/projects_controller_spec.rb
spec/controllers/projects_controller_spec.rb
+1
-1
spec/controllers/uploads_controller_spec.rb
spec/controllers/uploads_controller_spec.rb
+12
-12
spec/features/projects/pipelines/pipelines_spec.rb
spec/features/projects/pipelines/pipelines_spec.rb
+1
-4
spec/features/projects/tags/user_views_tags_spec.rb
spec/features/projects/tags/user_views_tags_spec.rb
+1
-1
spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap
...itory/components/preview/__snapshots__/index_spec.js.snap
+36
-0
spec/frontend/repository/components/preview/index_spec.js
spec/frontend/repository/components/preview/index_spec.js
+49
-0
spec/frontend/repository/components/table/index_spec.js
spec/frontend/repository/components/table/index_spec.js
+31
-35
spec/frontend/repository/components/tree_content_spec.js
spec/frontend/repository/components/tree_content_spec.js
+71
-0
spec/lib/constraints/project_url_constrainer_spec.rb
spec/lib/constraints/project_url_constrainer_spec.rb
+2
-29
spec/lib/gitlab/bitbucket_import/importer_spec.rb
spec/lib/gitlab/bitbucket_import/importer_spec.rb
+1
-0
spec/models/concerns/issuable_spec.rb
spec/models/concerns/issuable_spec.rb
+28
-0
spec/requests/projects/blob_controller_spec.rb
spec/requests/projects/blob_controller_spec.rb
+44
-0
spec/requests/user_avatar_spec.rb
spec/requests/user_avatar_spec.rb
+36
-0
spec/routing/project_routing_spec.rb
spec/routing/project_routing_spec.rb
+0
-4
spec/support/controllers/sessionless_auth_controller_shared_examples.rb
...ontrollers/sessionless_auth_controller_shared_examples.rb
+4
-18
spec/support/shared_examples/controllers/todos_shared_examples.rb
...port/shared_examples/controllers/todos_shared_examples.rb
+1
-1
No files found.
Gemfile.lock
View file @
d8ccc7a0
...
...
@@ -803,8 +803,8 @@ GEM
actionpack (>= 4.0, < 7)
redis-rack (>= 1, < 3)
redis-store (>= 1.1.0, < 2)
redis-activesupport (5.
0.7
)
activesupport (>= 3, <
6
)
redis-activesupport (5.
2.0
)
activesupport (>= 3, <
7
)
redis-store (>= 1.3, < 2)
redis-namespace (1.6.0)
redis (>= 3.0.4)
...
...
@@ -815,8 +815,8 @@ GEM
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
redis-store (1.
6.0
)
redis (>=
2.2
, < 5)
redis-store (1.
8.1
)
redis (>=
4
, < 5)
regexp_parser (1.5.1)
regexp_property_values (0.3.4)
representable (3.0.4)
...
...
app/assets/javascripts/repository/components/preview/index.vue
0 → 100644
View file @
d8ccc7a0
<
script
>
import
{
GlLink
,
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
getReadmeQuery
from
'
../../queries/getReadme.query.graphql
'
;
export
default
{
apollo
:
{
readme
:
{
query
:
getReadmeQuery
,
variables
()
{
return
{
url
:
this
.
blob
.
webUrl
,
};
},
loadingKey
:
'
loading
'
,
},
},
components
:
{
GlLink
,
GlLoadingIcon
,
},
props
:
{
blob
:
{
type
:
Object
,
required
:
true
,
},
},
data
()
{
return
{
readme
:
null
,
loading
:
0
,
};
},
};
</
script
>
<
template
>
<article
class=
"file-holder js-hide-on-navigation limited-width-container readme-holder"
>
<div
class=
"file-title"
>
<i
aria-hidden=
"true"
class=
"fa fa-file-text-o fa-fw"
></i>
<gl-link
:href=
"blob.webUrl"
>
<strong>
{{
blob
.
name
}}
</strong>
</gl-link>
</div>
<div
class=
"blob-viewer"
>
<gl-loading-icon
v-if=
"loading > 0"
size=
"md"
class=
"my-4 mx-auto"
/>
<div
v-else-if=
"readme"
v-html=
"readme.html"
></div>
</div>
</article>
</
template
>
app/assets/javascripts/repository/components/table/index.vue
View file @
d8ccc7a0
<
script
>
import
{
GlSkeletonLoading
}
from
'
@gitlab/ui
'
;
import
createFlash
from
'
~/flash
'
;
import
{
sprintf
,
__
}
from
'
../../../locale
'
;
import
getRefMixin
from
'
../../mixins/get_ref
'
;
import
getFiles
from
'
../../queries/getFiles.query.graphql
'
;
import
getProjectPath
from
'
../../queries/getProjectPath.query.graphql
'
;
import
TableHeader
from
'
./header.vue
'
;
import
TableRow
from
'
./row.vue
'
;
import
ParentRow
from
'
./parent_row.vue
'
;
const
PAGE_SIZE
=
100
;
export
default
{
components
:
{
GlSkeletonLoading
,
...
...
@@ -29,22 +25,24 @@ export default {
type
:
String
,
required
:
true
,
},
entries
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
({}),
},
isLoading
:
{
type
:
Boolean
,
required
:
true
,
},
},
data
()
{
return
{
projectPath
:
''
,
nextPageCursor
:
''
,
entries
:
{
trees
:
[],
submodules
:
[],
blobs
:
[],
},
isLoadingFiles
:
false
,
};
},
computed
:
{
tableCaption
()
{
if
(
this
.
isLoading
Files
)
{
if
(
this
.
isLoading
)
{
return
sprintf
(
__
(
'
Loading files, directories, and submodules in the path %{path} for commit reference %{ref}
'
,
...
...
@@ -59,65 +57,7 @@ export default {
);
},
showParentRow
()
{
return
!
this
.
isLoadingFiles
&&
[
''
,
'
/
'
].
indexOf
(
this
.
path
)
===
-
1
;
},
},
watch
:
{
$route
:
function
routeChange
()
{
this
.
entries
.
trees
=
[];
this
.
entries
.
submodules
=
[];
this
.
entries
.
blobs
=
[];
this
.
nextPageCursor
=
''
;
this
.
fetchFiles
();
},
},
mounted
()
{
// We need to wait for `ref` and `projectPath` to be set
this
.
$nextTick
(()
=>
this
.
fetchFiles
());
},
methods
:
{
fetchFiles
()
{
this
.
isLoadingFiles
=
true
;
return
this
.
$apollo
.
query
({
query
:
getFiles
,
variables
:
{
projectPath
:
this
.
projectPath
,
ref
:
this
.
ref
,
path
:
this
.
path
||
'
/
'
,
nextPageCursor
:
this
.
nextPageCursor
,
pageSize
:
PAGE_SIZE
,
},
})
.
then
(({
data
})
=>
{
if
(
!
data
)
return
;
const
pageInfo
=
this
.
hasNextPage
(
data
.
project
.
repository
.
tree
);
this
.
isLoadingFiles
=
false
;
this
.
entries
=
Object
.
keys
(
this
.
entries
).
reduce
(
(
acc
,
key
)
=>
({
...
acc
,
[
key
]:
this
.
normalizeData
(
key
,
data
.
project
.
repository
.
tree
[
key
].
edges
),
}),
{},
);
if
(
pageInfo
&&
pageInfo
.
hasNextPage
)
{
this
.
nextPageCursor
=
pageInfo
.
endCursor
;
this
.
fetchFiles
();
}
})
.
catch
(()
=>
createFlash
(
__
(
'
An error occurred while fetching folder content.
'
)));
},
normalizeData
(
key
,
data
)
{
return
this
.
entries
[
key
].
concat
(
data
.
map
(({
node
})
=>
node
));
},
hasNextPage
(
data
)
{
return
[]
.
concat
(
data
.
trees
.
pageInfo
,
data
.
submodules
.
pageInfo
,
data
.
blobs
.
pageInfo
)
.
find
(({
hasNextPage
})
=>
hasNextPage
);
return
!
this
.
isLoading
&&
[
''
,
'
/
'
].
indexOf
(
this
.
path
)
===
-
1
;
},
},
};
...
...
@@ -145,7 +85,7 @@ export default {
:lfs-oid="entry.lfsOid"
/>
</
template
>
<
template
v-if=
"isLoading
Files
"
>
<
template
v-if=
"isLoading"
>
<tr
v-for=
"i in 5"
:key=
"i"
aria-hidden=
"true"
>
<td><gl-skeleton-loading
:lines=
"1"
class=
"h-auto"
/></td>
<td><gl-skeleton-loading
:lines=
"1"
class=
"h-auto"
/></td>
...
...
app/assets/javascripts/repository/components/tree_content.vue
0 → 100644
View file @
d8ccc7a0
<
script
>
import
createFlash
from
'
~/flash
'
;
import
{
__
}
from
'
../../locale
'
;
import
FileTable
from
'
./table/index.vue
'
;
import
getRefMixin
from
'
../mixins/get_ref
'
;
import
getFiles
from
'
../queries/getFiles.query.graphql
'
;
import
getProjectPath
from
'
../queries/getProjectPath.query.graphql
'
;
import
FilePreview
from
'
./preview/index.vue
'
;
import
{
readmeFile
}
from
'
../utils/readme
'
;
const
PAGE_SIZE
=
100
;
export
default
{
components
:
{
FileTable
,
FilePreview
,
},
mixins
:
[
getRefMixin
],
apollo
:
{
projectPath
:
{
query
:
getProjectPath
,
},
},
props
:
{
path
:
{
type
:
String
,
required
:
false
,
default
:
'
/
'
,
},
},
data
()
{
return
{
projectPath
:
''
,
nextPageCursor
:
''
,
entries
:
{
trees
:
[],
submodules
:
[],
blobs
:
[],
},
isLoadingFiles
:
false
,
};
},
computed
:
{
readme
()
{
return
readmeFile
(
this
.
entries
.
blobs
);
},
},
watch
:
{
$route
:
function
routeChange
()
{
this
.
entries
.
trees
=
[];
this
.
entries
.
submodules
=
[];
this
.
entries
.
blobs
=
[];
this
.
nextPageCursor
=
''
;
this
.
fetchFiles
();
},
},
mounted
()
{
// We need to wait for `ref` and `projectPath` to be set
this
.
$nextTick
(()
=>
this
.
fetchFiles
());
},
methods
:
{
fetchFiles
()
{
this
.
isLoadingFiles
=
true
;
return
this
.
$apollo
.
query
({
query
:
getFiles
,
variables
:
{
projectPath
:
this
.
projectPath
,
ref
:
this
.
ref
,
path
:
this
.
path
||
'
/
'
,
nextPageCursor
:
this
.
nextPageCursor
,
pageSize
:
PAGE_SIZE
,
},
})
.
then
(({
data
})
=>
{
if
(
!
data
)
return
;
const
pageInfo
=
this
.
hasNextPage
(
data
.
project
.
repository
.
tree
);
this
.
isLoadingFiles
=
false
;
this
.
entries
=
Object
.
keys
(
this
.
entries
).
reduce
(
(
acc
,
key
)
=>
({
...
acc
,
[
key
]:
this
.
normalizeData
(
key
,
data
.
project
.
repository
.
tree
[
key
].
edges
),
}),
{},
);
if
(
pageInfo
&&
pageInfo
.
hasNextPage
)
{
this
.
nextPageCursor
=
pageInfo
.
endCursor
;
this
.
fetchFiles
();
}
})
.
catch
(()
=>
createFlash
(
__
(
'
An error occurred while fetching folder content.
'
)));
},
normalizeData
(
key
,
data
)
{
return
this
.
entries
[
key
].
concat
(
data
.
map
(({
node
})
=>
node
));
},
hasNextPage
(
data
)
{
return
[]
.
concat
(
data
.
trees
.
pageInfo
,
data
.
submodules
.
pageInfo
,
data
.
blobs
.
pageInfo
)
.
find
(({
hasNextPage
})
=>
hasNextPage
);
},
},
};
</
script
>
<
template
>
<div>
<file-table
:path=
"path"
:entries=
"entries"
:is-loading=
"isLoadingFiles"
/>
<file-preview
v-if=
"readme"
:blob=
"readme"
/>
</div>
</
template
>
app/assets/javascripts/repository/graphql.js
View file @
d8ccc7a0
import
Vue
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
IntrospectionFragmentMatcher
}
from
'
apollo-cache-inmemory
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
introspectionQueryResultData
from
'
./fragmentTypes.json
'
;
import
{
fetchLogsTree
}
from
'
./log_tree
'
;
...
...
@@ -27,6 +28,11 @@ const defaultClient = createDefaultClient(
});
});
},
readme
(
_
,
{
url
})
{
return
axios
.
get
(
url
,
{
params
:
{
viewer
:
'
rich
'
,
format
:
'
json
'
}
})
.
then
(({
data
})
=>
({
...
data
,
__typename
:
'
ReadmeFile
'
}));
},
},
},
{
...
...
app/assets/javascripts/repository/pages/index.vue
View file @
d8ccc7a0
<
script
>
import
FileTable
from
'
../components/table/index
.vue
'
;
import
TreeContent
from
'
../components/tree_content
.vue
'
;
export
default
{
components
:
{
FileTable
,
},
data
()
{
return
{
ref
:
''
,
};
TreeContent
,
},
};
</
script
>
<
template
>
<
file-table
path=
"/"
/>
<
tree-content
/>
</
template
>
app/assets/javascripts/repository/pages/tree.vue
View file @
d8ccc7a0
<
script
>
import
FileTable
from
'
../components/table/index
.vue
'
;
import
TreeContent
from
'
../components/tree_content
.vue
'
;
export
default
{
components
:
{
FileTable
,
TreeContent
,
},
props
:
{
path
:
{
...
...
@@ -16,5 +16,5 @@ export default {
</
script
>
<
template
>
<
file-table
:path=
"path"
/>
<
tree-content
:path=
"path"
/>
</
template
>
app/assets/javascripts/repository/queries/getReadme.query.graphql
0 → 100644
View file @
d8ccc7a0
query
getReadme
(
$url
:
String
!)
{
readme
(
url
:
$url
)
@client
{
html
}
}
app/assets/javascripts/repository/utils/readme.js
0 → 100644
View file @
d8ccc7a0
const
MARKDOWN_EXTENSIONS
=
[
'
mdown
'
,
'
mkd
'
,
'
mkdn
'
,
'
md
'
,
'
markdown
'
];
const
ASCIIDOC_EXTENSIONS
=
[
'
adoc
'
,
'
ad
'
,
'
asciidoc
'
];
const
OTHER_EXTENSIONS
=
[
'
textile
'
,
'
rdoc
'
,
'
org
'
,
'
creole
'
,
'
wiki
'
,
'
mediawiki
'
,
'
rst
'
];
const
EXTENSIONS
=
[...
MARKDOWN_EXTENSIONS
,
...
ASCIIDOC_EXTENSIONS
,
...
OTHER_EXTENSIONS
];
const
PLAIN_FILENAMES
=
[
'
readme
'
,
'
index
'
];
const
FILE_REGEXP
=
new
RegExp
(
`^(
${
PLAIN_FILENAMES
.
join
(
'
|
'
)}
)`
,
'
i
'
);
const
EXTENSIONS_REGEXP
=
new
RegExp
(
`.(
${
EXTENSIONS
.
join
(
'
|
'
)}
)$`
,
'
i
'
);
// eslint-disable-next-line import/prefer-default-export
export
const
readmeFile
=
blobs
=>
{
const
readMeFiles
=
blobs
.
filter
(
f
=>
f
.
name
.
search
(
FILE_REGEXP
)
!==
-
1
);
const
previewableReadme
=
readMeFiles
.
find
(
f
=>
f
.
name
.
search
(
EXTENSIONS_REGEXP
)
!==
-
1
);
const
plainReadme
=
readMeFiles
.
find
(
f
=>
f
.
name
.
search
(
FILE_REGEXP
)
!==
-
1
);
return
previewableReadme
||
plainReadme
;
};
app/assets/stylesheets/framework/snippets.scss
View file @
d8ccc7a0
...
...
@@ -4,7 +4,12 @@
}
.snippet-filename
{
padding
:
0
2px
;
color
:
$gl-text-color-secondary
;
font-weight
:
normal
;
}
.snippet-info
{
color
:
$gl-text-color-secondary
;
}
}
...
...
app/controllers/application_controller.rb
View file @
d8ccc7a0
...
...
@@ -17,14 +17,14 @@ class ApplicationController < ActionController::Base
include
Gitlab
::
Tracking
::
ControllerConcern
include
Gitlab
::
Experimentation
::
ControllerConcern
before_action
:authenticate_user!
,
except:
[
:route_not_found
]
before_action
:authenticate_user!
before_action
:enforce_terms!
,
if: :should_enforce_terms?
before_action
:validate_user_service_ticket!
before_action
:check_password_expiration
before_action
:check_password_expiration
,
if: :html_request?
before_action
:ldap_security_check
before_action
:sentry_context
before_action
:default_headers
before_action
:add_gon_variables
,
unless:
[
:peek_request?
,
:json_request?
]
before_action
:add_gon_variables
,
if: :html_request?
before_action
:configure_permitted_parameters
,
if: :devise_controller?
before_action
:require_email
,
unless: :devise_controller?
before_action
:active_user_check
,
unless: :devise_controller?
...
...
@@ -95,13 +95,11 @@ class ApplicationController < ActionController::Base
end
def
route_not_found
if
current_user
not_found
else
store_location_for
(
:user
,
request
.
fullpath
)
unless
request
.
xhr?
# We need to call #authenticate_user! here because sometimes this is called from another action
# and not from our wildcard fallback route
authenticate_user!
redirect_to
new_user_session_path
,
alert:
I18n
.
t
(
'devise.failure.unauthenticated'
)
end
not_found
end
def
render
(
*
args
)
...
...
@@ -451,8 +449,8 @@ class ApplicationController < ActionController::Base
response
.
headers
[
'Page-Title'
]
=
URI
.
escape
(
page_title
(
'GitLab'
))
end
def
peek
_request?
request
.
path
.
start_with?
(
'/-/peek'
)
def
html
_request?
request
.
format
.
html?
end
def
json_request?
...
...
@@ -462,7 +460,7 @@ class ApplicationController < ActionController::Base
def
should_enforce_terms?
return
false
unless
Gitlab
::
CurrentSettings
.
current_application_settings
.
enforce_terms
!
(
peek_request?
||
devise_controller?
)
html_request?
&&
!
devise_controller?
end
def
set_usage_stats_consent_flag
...
...
app/controllers/concerns/confirm_email_warning.rb
View file @
d8ccc7a0
...
...
@@ -4,15 +4,18 @@ module ConfirmEmailWarning
extend
ActiveSupport
::
Concern
included
do
before_action
:set_confirm_warning
,
if:
->
{
Feature
.
enabled?
(
:soft_email_confirmation
)
}
before_action
:set_confirm_warning
,
if:
:show_confirm_warning?
end
protected
def
show_confirm_warning?
html_request?
&&
request
.
get?
&&
Feature
.
enabled?
(
:soft_email_confirmation
)
end
def
set_confirm_warning
return
unless
current_user
return
if
current_user
.
confirmed?
return
if
peek_request?
||
json_request?
||
!
request
.
get?
email
=
current_user
.
unconfirmed_email
||
current_user
.
email
...
...
app/controllers/concerns/uploads_actions.rb
View file @
d8ccc7a0
# frozen_string_literal: true
module
UploadsActions
extend
ActiveSupport
::
Concern
include
Gitlab
::
Utils
::
StrongMemoize
include
SendFileUpload
UPLOAD_MOUNTS
=
%w(avatar attachment file logo header_logo favicon)
.
freeze
included
do
prepend_before_action
:set_request_format_from_path_extension
end
def
create
uploader
=
UploadService
.
new
(
model
,
params
[
:file
],
uploader_class
).
execute
...
...
@@ -64,6 +69,18 @@ module UploadsActions
private
# From ActionDispatch::Http::MimeNegotiation. We have an initializer that
# monkey-patches this method out (so that repository paths don't guess a
# format based on extension), but we do want this behaviour when serving
# uploads.
def
set_request_format_from_path_extension
path
=
request
.
headers
[
'action_dispatch.original_path'
]
||
request
.
headers
[
'PATH_INFO'
]
if
match
=
path
&
.
match
(
/\.(\w+)\z/
)
request
.
format
=
match
.
captures
.
first
end
end
def
uploader_class
raise
NotImplementedError
end
...
...
app/controllers/uploads_controller.rb
View file @
d8ccc7a0
...
...
@@ -20,7 +20,7 @@ class UploadsController < ApplicationController
skip_before_action
:authenticate_user!
before_action
:upload_mount_satisfied?
before_action
:
find_
model
before_action
:model
before_action
:authorize_access!
,
only:
[
:show
]
before_action
:authorize_create_access!
,
only:
[
:create
,
:authorize
]
before_action
:verify_workhorse_api!
,
only:
[
:authorize
]
...
...
app/models/concerns/issuable.rb
View file @
d8ccc7a0
...
...
@@ -137,6 +137,26 @@ module Issuable
strip_attributes
:title
# The state_machine gem will reset the value of state_id unless it
# is a raw attribute passed in here:
# https://gitlab.com/gitlab-org/gitlab/issues/35746#note_241148787
#
# This assumes another initialize isn't defined. Otherwise this
# method may need to be prepended.
def
initialize
(
attributes
=
nil
)
if
attributes
.
is_a?
(
Hash
)
attr
=
attributes
.
symbolize_keys
if
attr
.
key?
(
:state
)
&&
!
attr
.
key?
(
:state_id
)
value
=
attr
.
delete
(
:state
)
state_id
=
self
.
class
.
available_states
[
value
]
attributes
[
:state_id
]
=
state_id
if
state_id
end
end
super
(
attributes
)
end
# We want to use optimistic lock for cases when only title or description are involved
# http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
def
locking_enabled?
...
...
app/views/import/manifest/_form.html.haml
View file @
d8ccc7a0
...
...
@@ -13,7 +13,7 @@
.form-group
=
label_tag
:manifest
,
class:
'label-bold'
do
=
_
(
'Manifest'
)
=
file_field_tag
:manifest
,
class:
'form-control-file'
,
required:
true
=
file_field_tag
:manifest
,
class:
'form-control-file
w-auto
'
,
required:
true
.form-text.text-muted
=
_
(
'Import multiple repositories by uploading a manifest file.'
)
=
link_to
icon
(
'question-circle'
),
help_page_path
(
'user/project/import/manifest'
)
...
...
app/views/projects/_files.html.haml
View file @
d8ccc7a0
...
...
@@ -23,7 +23,5 @@
-
if
can_edit_tree?
=
render
'projects/blob/upload'
,
title:
_
(
'Upload New File'
),
placeholder:
_
(
'Upload New File'
),
button_title:
_
(
'Upload file'
),
form_path:
project_create_blob_path
(
@project
,
@id
),
method: :post
=
render
'projects/blob/new_dir'
-
if
@tree
.
readme
=
render
"projects/tree/readme"
,
readme:
@tree
.
readme
-
else
=
render
'projects/tree/tree_content'
,
tree:
@tree
,
content_url:
content_url
app/views/shared/snippets/_snippet.html.haml
View file @
d8ccc7a0
...
...
@@ -7,8 +7,9 @@
.title
=
link_to
reliable_snippet_path
(
snippet
)
do
=
snippet
.
title
-
if
snippet
.
file_name
%span
.snippet-filename.monospace.d-none.d-sm-inline-block
-
if
snippet
.
file_name
.
present?
%span
.snippet-filename.d-none.d-sm-inline-block.ml-2
=
sprite_icon
(
'doc-code'
,
size:
16
,
css_class:
'file-icon align-text-bottom'
)
=
snippet
.
file_name
%ul
.controls
...
...
changelogs/unreleased/28350-manifest-error-file-attach.yml
0 → 100644
View file @
d8ccc7a0
---
title
:
Add max width on manifest file attachment input
merge_request
:
19028
author
:
type
:
fixed
changelogs/unreleased/31964-make-snippet-list-easier-to-scan.yml
0 → 100644
View file @
d8ccc7a0
---
title
:
Make snippet list easier to scan
merge_request
:
19490
author
:
type
:
other
changelogs/unreleased/35289-remove-existence-check-in-url-constrainer.yml
0 → 100644
View file @
d8ccc7a0
---
title
:
Fix JSON responses returning 302 instead of
401
merge_request
:
19412
author
:
type
:
fixed
changelogs/unreleased/allow-container-scanning-to-run-offline.yml
0 → 100644
View file @
d8ccc7a0
---
title
:
Allow container scanning to run offline by specifying the Clair DB image to use.
merge_request
:
19161
author
:
type
:
changed
changelogs/unreleased/sh-fix-bitbucket-importer-pr-state.yml
0 → 100644
View file @
d8ccc7a0
---
title
:
Fix Bitbucket Cloud importer pull request state
merge_request
:
19734
author
:
type
:
fixed
config/routes/git_http.rb
View file @
d8ccc7a0
...
...
@@ -52,7 +52,7 @@ scope(path: '*namespace_id/:project_id',
# /info/refs?service=git-receive-pack, but nothing else.
#
git_http_handshake
=
lambda
do
|
request
|
::
Constraints
::
ProjectUrlConstrainer
.
new
.
matches?
(
request
,
existence_check:
false
)
&&
::
Constraints
::
ProjectUrlConstrainer
.
new
.
matches?
(
request
)
&&
(
request
.
query_string
.
blank?
||
request
.
query_string
.
match
(
/\Aservice=git-(upload|receive)-pack\z/
))
end
...
...
config/routes/project.rb
View file @
d8ccc7a0
...
...
@@ -245,12 +245,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post
:validate_query
,
on: :collection
end
end
Gitlab
.
ee
do
resources
:alerts
,
constraints:
{
id:
/\d+/
},
only:
[
:index
,
:create
,
:show
,
:update
,
:destroy
]
do
post
:notify
,
on: :collection
end
end
end
resources
:merge_requests
,
concerns: :awardable
,
except:
[
:new
,
:create
,
:show
],
constraints:
{
id:
/\d+/
}
do
...
...
@@ -353,17 +347,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
Gitlab
.
ee
do
resources
:path_locks
,
only:
[
:index
,
:destroy
]
do
collection
do
post
:toggle
end
end
get
'/service_desk'
=>
'service_desk#show'
,
as: :service_desk
put
'/service_desk'
=>
'service_desk#update'
,
as: :service_desk_refresh
end
resource
:variables
,
only:
[
:show
,
:update
]
resources
:triggers
,
only:
[
:index
,
:create
,
:edit
,
:update
,
:destroy
]
...
...
@@ -397,11 +380,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get
:failures
get
:status
get
:test_report
Gitlab
.
ee
do
get
:security
get
:licenses
end
end
member
do
...
...
@@ -536,24 +514,11 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get
:realtime_changes
post
:create_merge_request
get
:discussions
,
format: :json
Gitlab
.
ee
do
get
'designs(/*vueroute)'
,
to:
'issues#designs'
,
as: :designs
,
format:
false
end
end
collection
do
post
:bulk_update
post
:import_csv
Gitlab
.
ee
do
post
:export_csv
get
:service_desk
end
end
Gitlab
.
ee
do
resources
:issue_links
,
only:
[
:index
,
:create
,
:destroy
],
as:
'links'
,
path:
'links'
end
end
...
...
@@ -629,6 +594,15 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
Gitlab
.
ee
do
resources
:managed_licenses
,
only:
[
:index
,
:show
,
:new
,
:create
,
:edit
,
:update
,
:destroy
]
end
# Legacy routes.
# Introduced in 12.0.
# Should be removed after 12.1
Gitlab
::
Routing
.
redirect_legacy_paths
(
self
,
:settings
,
:branches
,
:tags
,
:network
,
:graphs
,
:autocomplete_sources
,
:project_members
,
:deploy_keys
,
:deploy_tokens
,
:labels
,
:milestones
,
:services
,
:boards
,
:releases
,
:forks
,
:group_links
,
:import
,
:avatar
)
end
resources
(
:projects
,
...
...
@@ -653,22 +627,4 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
end
# Legacy routes.
# Introduced in 12.0.
# Should be removed after 12.1
scope
(
path:
'*namespace_id'
,
as: :namespace
,
namespace_id:
Gitlab
::
PathRegex
.
full_namespace_route_regex
)
do
scope
(
path:
':project_id'
,
constraints:
{
project_id:
Gitlab
::
PathRegex
.
project_route_regex
},
module: :projects
,
as: :project
)
do
Gitlab
::
Routing
.
redirect_legacy_paths
(
self
,
:settings
,
:branches
,
:tags
,
:network
,
:graphs
,
:autocomplete_sources
,
:project_members
,
:deploy_keys
,
:deploy_tokens
,
:labels
,
:milestones
,
:services
,
:boards
,
:releases
,
:forks
,
:group_links
,
:import
,
:avatar
)
end
end
end
lib/constraints/project_url_constrainer.rb
View file @
d8ccc7a0
...
...
@@ -2,17 +2,12 @@
module
Constraints
class
ProjectUrlConstrainer
def
matches?
(
request
,
existence_check:
true
)
def
matches?
(
request
)
namespace_path
=
request
.
params
[
:namespace_id
]
project_path
=
request
.
params
[
:project_id
]
||
request
.
params
[
:id
]
full_path
=
[
namespace_path
,
project_path
].
join
(
'/'
)
return
false
unless
ProjectPathValidator
.
valid_path?
(
full_path
)
return
true
unless
existence_check
# We intentionally allow SELECT(*) here so result of this query can be used
# as cache for further Project.find_by_full_path calls within request
Project
.
find_by_full_path
(
full_path
,
follow_redirects:
request
.
get?
).
present?
ProjectPathValidator
.
valid_path?
(
full_path
)
end
end
end
lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
View file @
d8ccc7a0
...
...
@@ -9,16 +9,17 @@ container_scanning:
name
:
registry.gitlab.com/gitlab-org/security-products/analyzers/klar:$CS_MAJOR_VERSION
entrypoint
:
[]
variables
:
# By default, use the latest clair vulnerabilities database, however, allow it to be overridden here
# with a specific version to provide consistency for integration testing purposes
CLAIR_DB_IMAGE_TAG
:
latest
# Override this variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yaml` file.
# See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
# By default, use the latest clair vulnerabilities database, however, allow it to be overridden here with a specific image
# to enable container scanning to run offline, or to provide a consistent list of vulnerabilities for integration testing purposes
CLAIR_DB_IMAGE_TAG
:
"
latest"
CLAIR_DB_IMAGE
:
"
arminc/clair-db:$CLAIR_DB_IMAGE_TAG"
# Override the GIT_STRATEGY variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yml`
# file. See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
# for details
GIT_STRATEGY
:
none
allow_failure
:
true
services
:
-
name
:
arminc/clair-db:$CLAIR_DB_IMAGE_TAG
-
name
:
$CLAIR_DB_IMAGE
alias
:
clair-vulnerabilities-db
script
:
# the kubernetes executor currently ignores the Docker image entrypoint value, so the start.sh script must
...
...
lib/gitlab/patch/draw_route.rb
View file @
d8ccc7a0
...
...
@@ -10,7 +10,7 @@ module Gitlab
RoutesNotFound
=
Class
.
new
(
StandardError
)
def
draw
(
routes_name
)
drawn_any
=
draw_
ce
(
routes_name
)
|
draw_e
e
(
routes_name
)
drawn_any
=
draw_
ee
(
routes_name
)
|
draw_c
e
(
routes_name
)
drawn_any
||
raise
(
RoutesNotFound
.
new
(
"Cannot find
#{
routes_name
}
"
))
end
...
...
spec/controllers/application_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -90,14 +90,6 @@ describe ApplicationController do
let
(
:format
)
{
:html
}
it_behaves_like
'setting gon variables'
context
'for peek requests'
do
before
do
request
.
path
=
'/-/peek'
end
it_behaves_like
'not setting gon variables'
end
end
context
'with json format'
do
...
...
@@ -105,6 +97,12 @@ describe ApplicationController do
it_behaves_like
'not setting gon variables'
end
context
'with atom format'
do
let
(
:format
)
{
:atom
}
it_behaves_like
'not setting gon variables'
end
end
describe
'session expiration'
do
...
...
@@ -186,7 +184,7 @@ describe ApplicationController do
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
it
'redirects to login page if not authenticated'
do
it
'redirects to login page
via authenticate_user!
if not authenticated'
do
get
:index
expect
(
response
).
to
redirect_to
new_user_session_path
...
...
spec/controllers/projects/commits_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -142,7 +142,7 @@ describe Projects::CommitsController do
context
'token authentication'
do
context
'public project'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
{
public:
true
,
ignore_incrementing:
true
}
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
true
do
before
do
public_project
=
create
(
:project
,
:repository
,
:public
)
...
...
@@ -152,7 +152,7 @@ describe Projects::CommitsController do
end
context
'private project'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
{
public:
false
,
ignore_incrementing:
true
}
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
false
do
before
do
private_project
=
create
(
:project
,
:repository
,
:private
)
private_project
.
add_maintainer
(
user
)
...
...
spec/controllers/projects/error_tracking_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -146,7 +146,7 @@ describe Projects::ErrorTrackingController do
it
'redirects to sign-in page'
do
post
:list_projects
,
params:
list_projects_params
expect
(
response
).
to
have_gitlab_http_status
(
:
redirect
)
expect
(
response
).
to
have_gitlab_http_status
(
:
unauthorized
)
end
end
...
...
spec/controllers/projects/issues_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -1441,7 +1441,7 @@ describe Projects::IssuesController do
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
,
ignore_incrementing:
true
do
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
...
...
@@ -1449,7 +1449,7 @@ describe Projects::IssuesController do
end
end
it_behaves_like
'authenticates sessionless user'
,
:calendar
,
:ics
,
ignore_incrementing:
true
do
it_behaves_like
'authenticates sessionless user'
,
:calendar
,
:ics
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
...
...
spec/controllers/projects/releases_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -111,8 +111,8 @@ describe Projects::ReleasesController do
context
'when the project is private and the user is not logged in'
do
let
(
:project
)
{
private_project
}
it
'returns a
redirect
'
do
expect
(
response
).
to
have_gitlab_http_status
(
:
redirect
)
it
'returns a
401
'
do
expect
(
response
).
to
have_gitlab_http_status
(
:
unauthorized
)
end
end
end
...
...
spec/controllers/projects/tags_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -41,7 +41,7 @@ describe Projects::TagsController do
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:repository
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
,
ignore_incrementing:
true
do
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
...
...
spec/controllers/projects_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -1149,7 +1149,7 @@ describe ProjectsController do
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
ignore_incrementing:
true
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
do
before
do
default_params
.
merge!
(
id:
private_project
,
namespace_id:
private_project
.
namespace
)
...
...
spec/controllers/uploads_controller_spec.rb
View file @
d8ccc7a0
...
...
@@ -228,10 +228,10 @@ describe UploadsController do
user
.
block
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"user"
,
mounted_as:
"avatar"
,
id:
user
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -320,10 +320,10 @@ describe UploadsController do
end
context
"when not signed in"
do
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"project"
,
mounted_as:
"avatar"
,
id:
project
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -343,10 +343,10 @@ describe UploadsController do
project
.
add_maintainer
(
user
)
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"project"
,
mounted_as:
"avatar"
,
id:
project
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -439,10 +439,10 @@ describe UploadsController do
user
.
block
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"group"
,
mounted_as:
"avatar"
,
id:
group
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -526,10 +526,10 @@ describe UploadsController do
end
context
"when not signed in"
do
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"note"
,
mounted_as:
"attachment"
,
id:
note
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -549,10 +549,10 @@ describe UploadsController do
project
.
add_maintainer
(
user
)
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"note"
,
mounted_as:
"attachment"
,
id:
note
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
spec/features/projects/pipelines/pipelines_spec.rb
View file @
d8ccc7a0
...
...
@@ -819,10 +819,7 @@ describe 'Pipelines', :js do
context
'when project is private'
do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
it
'redirects the user to sign_in and displays the flash alert'
do
expect
(
page
).
to
have_content
'You need to sign in'
expect
(
page
.
current_path
).
to
eq
(
"/users/sign_in"
)
end
it
{
expect
(
page
).
to
have_content
'You need to sign in'
}
end
end
...
...
spec/features/projects/tags/user_views_tags_spec.rb
View file @
d8ccc7a0
...
...
@@ -15,7 +15,7 @@ describe 'User views tags', :feature do
it
do
visit
project_tags_path
(
project
,
format: :atom
)
expect
(
page
.
current_path
).
to
eq
(
"/users/sign_in"
)
expect
(
page
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
spec/frontend/repository/components/preview/__snapshots__/index_spec.js.snap
0 → 100644
View file @
d8ccc7a0
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Repository file preview component renders file HTML 1`] = `
<article
class="file-holder js-hide-on-navigation limited-width-container readme-holder"
>
<div
class="file-title"
>
<i
aria-hidden="true"
class="fa fa-file-text-o fa-fw"
/>
<gllink-stub
href="http://test.com"
>
<strong>
README.md
</strong>
</gllink-stub>
</div>
<div
class="blob-viewer"
>
<div>
<div
class="blob"
>
test
</div>
</div>
</div>
</article>
`;
spec/frontend/repository/components/preview/index_spec.js
0 → 100644
View file @
d8ccc7a0
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
Preview
from
'
~/repository/components/preview/index.vue
'
;
let
vm
;
let
$apollo
;
function
factory
(
blob
)
{
$apollo
=
{
query
:
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
({})),
};
vm
=
shallowMount
(
Preview
,
{
propsData
:
{
blob
,
},
mocks
:
{
$apollo
,
},
});
}
describe
(
'
Repository file preview component
'
,
()
=>
{
afterEach
(()
=>
{
vm
.
destroy
();
});
it
(
'
renders file HTML
'
,
()
=>
{
factory
({
webUrl
:
'
http://test.com
'
,
name
:
'
README.md
'
,
});
vm
.
setData
({
readme
:
{
html
:
'
<div class="blob">test</div>
'
}
});
expect
(
vm
.
element
).
toMatchSnapshot
();
});
it
(
'
renders loading icon
'
,
()
=>
{
factory
({
webUrl
:
'
http://test.com
'
,
name
:
'
README.md
'
,
});
vm
.
setData
({
loading
:
1
});
expect
(
vm
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
});
});
spec/frontend/repository/components/table/index_spec.js
View file @
d8ccc7a0
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlSkeletonLoading
}
from
'
@gitlab/ui
'
;
import
Table
from
'
~/repository/components/table/index.vue
'
;
import
TableRow
from
'
~/repository/components/table/row.vue
'
;
let
vm
;
let
$apollo
;
function
factory
(
path
,
data
=
()
=>
({}))
{
$apollo
=
{
query
:
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
({
data
:
data
()
})),
};
const
MOCK_BLOBS
=
[
{
id
:
'
123abc
'
,
flatPath
:
'
blob
'
,
name
:
'
blob.md
'
,
type
:
'
blob
'
,
webUrl
:
'
http://test.com
'
,
},
{
id
:
'
124abc
'
,
flatPath
:
'
blob2
'
,
name
:
'
blob2.md
'
,
type
:
'
blob
'
,
webUrl
:
'
http://test.com
'
,
},
];
function
factory
({
path
,
isLoading
=
false
,
entries
=
{}
})
{
vm
=
shallowMount
(
Table
,
{
propsData
:
{
path
,
isLoading
,
entries
,
},
mocks
:
{
$apollo
,
...
...
@@ -31,7 +47,7 @@ describe('Repository table component', () => {
${
'
app/assets
'
}
|
${
'
master
'
}
${
'
/
'
}
|
${
'
test
'
}
`
(
'
renders table caption for $ref in $path
'
,
({
path
,
ref
})
=>
{
factory
(
path
);
factory
(
{
path
}
);
vm
.
setData
({
ref
});
...
...
@@ -41,40 +57,20 @@ describe('Repository table component', () => {
});
it
(
'
shows loading icon
'
,
()
=>
{
factory
(
'
/
'
);
vm
.
setData
({
isLoadingFiles
:
true
});
factory
({
path
:
'
/
'
,
isLoading
:
true
});
expect
(
vm
.
find
(
GlSkeletonLoading
).
exists
()).
toBe
(
true
);
});
describe
(
'
normalizeData
'
,
()
=>
{
it
(
'
normalizes edge nodes
'
,
()
=>
{
const
output
=
vm
.
vm
.
normalizeData
(
'
blobs
'
,
[{
node
:
'
1
'
},
{
node
:
'
2
'
}]);
expect
(
output
).
toEqual
([
'
1
'
,
'
2
'
]);
it
(
'
renders table rows
'
,
()
=>
{
factory
({
path
:
'
/
'
,
entries
:
{
blobs
:
MOCK_BLOBS
,
},
});
});
describe
(
'
hasNextPage
'
,
()
=>
{
it
(
'
returns undefined when hasNextPage is false
'
,
()
=>
{
const
output
=
vm
.
vm
.
hasNextPage
({
trees
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
submodules
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
blobs
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
});
expect
(
output
).
toBe
(
undefined
);
});
it
(
'
returns pageInfo object when hasNextPage is true
'
,
()
=>
{
const
output
=
vm
.
vm
.
hasNextPage
({
trees
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
submodules
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
blobs
:
{
pageInfo
:
{
hasNextPage
:
true
,
nextCursor
:
'
test
'
}
},
});
expect
(
output
).
toEqual
({
hasNextPage
:
true
,
nextCursor
:
'
test
'
});
});
expect
(
vm
.
find
(
TableRow
).
exists
()).
toBe
(
true
);
expect
(
vm
.
findAll
(
TableRow
).
length
).
toBe
(
2
);
});
});
spec/frontend/repository/components/tree_content_spec.js
0 → 100644
View file @
d8ccc7a0
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
TreeContent
from
'
~/repository/components/tree_content.vue
'
;
import
FilePreview
from
'
~/repository/components/preview/index.vue
'
;
let
vm
;
let
$apollo
;
function
factory
(
path
,
data
=
()
=>
({}))
{
$apollo
=
{
query
:
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
({
data
:
data
()
})),
};
vm
=
shallowMount
(
TreeContent
,
{
propsData
:
{
path
,
},
mocks
:
{
$apollo
,
},
});
}
describe
(
'
Repository table component
'
,
()
=>
{
afterEach
(()
=>
{
vm
.
destroy
();
});
it
(
'
renders file preview
'
,
()
=>
{
factory
(
'
/
'
);
vm
.
setData
({
entries
:
{
blobs
:
[{
name
:
'
README.md
'
}]
}
});
expect
(
vm
.
find
(
FilePreview
).
exists
()).
toBe
(
true
);
});
describe
(
'
normalizeData
'
,
()
=>
{
it
(
'
normalizes edge nodes
'
,
()
=>
{
factory
(
'
/
'
);
const
output
=
vm
.
vm
.
normalizeData
(
'
blobs
'
,
[{
node
:
'
1
'
},
{
node
:
'
2
'
}]);
expect
(
output
).
toEqual
([
'
1
'
,
'
2
'
]);
});
});
describe
(
'
hasNextPage
'
,
()
=>
{
it
(
'
returns undefined when hasNextPage is false
'
,
()
=>
{
factory
(
'
/
'
);
const
output
=
vm
.
vm
.
hasNextPage
({
trees
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
submodules
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
blobs
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
});
expect
(
output
).
toBe
(
undefined
);
});
it
(
'
returns pageInfo object when hasNextPage is true
'
,
()
=>
{
factory
(
'
/
'
);
const
output
=
vm
.
vm
.
hasNextPage
({
trees
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
submodules
:
{
pageInfo
:
{
hasNextPage
:
false
}
},
blobs
:
{
pageInfo
:
{
hasNextPage
:
true
,
nextCursor
:
'
test
'
}
},
});
expect
(
output
).
toEqual
({
hasNextPage
:
true
,
nextCursor
:
'
test
'
});
});
});
});
spec/lib/constraints/project_url_constrainer_spec.rb
View file @
d8ccc7a0
...
...
@@ -14,42 +14,15 @@ describe Constraints::ProjectUrlConstrainer do
end
context
'invalid request'
do
context
"non-existing project"
do
let
(
:request
)
{
build_request
(
'foo'
,
'bar'
)
}
it
{
expect
(
subject
.
matches?
(
request
)).
to
be_falsey
}
context
'existence_check is false'
do
it
{
expect
(
subject
.
matches?
(
request
,
existence_check:
false
)).
to
be_truthy
}
end
end
context
"project id ending with .git"
do
let
(
:request
)
{
build_request
(
namespace
.
full_path
,
project
.
path
+
'.git'
)
}
it
{
expect
(
subject
.
matches?
(
request
)).
to
be_falsey
}
end
end
context
'when the request matches a redirect route'
do
let
(
:old_project_path
)
{
'old_project_path'
}
let!
(
:redirect_route
)
{
project
.
redirect_routes
.
create!
(
path:
"
#{
namespace
.
full_path
}
/
#{
old_project_path
}
"
)
}
context
'and is a GET request'
do
let
(
:request
)
{
build_request
(
namespace
.
full_path
,
old_project_path
)
}
it
{
expect
(
subject
.
matches?
(
request
)).
to
be_truthy
}
end
context
'and is NOT a GET request'
do
let
(
:request
)
{
build_request
(
namespace
.
full_path
,
old_project_path
,
'POST'
)
}
it
{
expect
(
subject
.
matches?
(
request
)).
to
be_falsey
}
end
end
end
def
build_request
(
namespace
,
project
,
method
=
'GET'
)
double
(
:request
,
'get?'
:
(
method
==
'GET'
),
params:
{
namespace_id:
namespace
,
id:
project
})
def
build_request
(
namespace
,
project
)
double
(
:request
,
params:
{
namespace_id:
namespace
,
id:
project
})
end
end
spec/lib/gitlab/bitbucket_import/importer_spec.rb
View file @
d8ccc7a0
...
...
@@ -158,6 +158,7 @@ describe Gitlab::BitbucketImport::Importer do
expect
{
subject
.
execute
}.
to
change
{
MergeRequest
.
count
}.
by
(
1
)
merge_request
=
MergeRequest
.
first
expect
(
merge_request
.
state
).
to
eq
(
'merged'
)
expect
(
merge_request
.
notes
.
count
).
to
eq
(
2
)
expect
(
merge_request
.
notes
.
map
(
&
:discussion_id
).
uniq
.
count
).
to
eq
(
1
)
...
...
spec/models/concerns/issuable_spec.rb
View file @
d8ccc7a0
...
...
@@ -111,6 +111,34 @@ describe Issuable do
end
end
describe
'.initialize'
do
it
'maps the state to the right state_id'
do
described_class
::
STATE_ID_MAP
.
each
do
|
key
,
value
|
issuable
=
MergeRequest
.
new
(
state:
key
)
expect
(
issuable
.
state
).
to
eq
(
key
)
expect
(
issuable
.
state_id
).
to
eq
(
value
)
end
end
it
'maps a string version of the state to the right state_id'
do
described_class
::
STATE_ID_MAP
.
each
do
|
key
,
value
|
issuable
=
MergeRequest
.
new
(
'state'
=>
key
)
expect
(
issuable
.
state
).
to
eq
(
key
)
expect
(
issuable
.
state_id
).
to
eq
(
value
)
end
end
it
'gives preference to state_id if present'
do
issuable
=
MergeRequest
.
new
(
'state'
=>
'opened'
,
'state_id'
=>
described_class
::
STATE_ID_MAP
[
'merged'
])
expect
(
issuable
.
state
).
to
eq
(
'merged'
)
expect
(
issuable
.
state_id
).
to
eq
(
described_class
::
STATE_ID_MAP
[
'merged'
])
end
end
describe
'#milestone_available?'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
...
...
spec/requests/projects/blob_controller_spec.rb
0 → 100644
View file @
d8ccc7a0
# frozen_string_literal: true
require
'spec_helper'
describe
Projects
::
BlobController
do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
let
(
:namespace
)
{
project
.
namespace
}
context
'anonymous user views blob in inaccessible project'
do
context
'with default HTML format'
do
before
do
get
namespace_project_blob_path
(
namespace_id:
namespace
,
project_id:
project
,
id:
'master/README.md'
)
end
context
'when project is private'
do
it
{
expect
(
response
).
to
have_gitlab_http_status
(
:redirect
)
}
end
context
'when project does not exist'
do
let
(
:namespace
)
{
'non_existent_namespace'
}
let
(
:project
)
{
'non_existent_project'
}
it
{
expect
(
response
).
to
have_gitlab_http_status
(
:redirect
)
}
end
end
context
'with JSON format'
do
before
do
get
namespace_project_blob_path
(
namespace_id:
namespace
,
project_id:
project
,
id:
'master/README.md'
,
format: :json
)
end
context
'when project is private'
do
it
{
expect
(
response
).
to
have_gitlab_http_status
(
:unauthorized
)
}
end
context
'when project does not exist'
do
let
(
:namespace
)
{
'non_existent_namespace'
}
let
(
:project
)
{
'non_existent_project'
}
it
{
expect
(
response
).
to
have_gitlab_http_status
(
:unauthorized
)
}
end
end
end
end
spec/requests/user_avatar_spec.rb
0 → 100644
View file @
d8ccc7a0
# frozen_string_literal: true
require
'spec_helper'
describe
'Loading a user avatar'
do
let
(
:user
)
{
create
(
:user
,
:with_avatar
)
}
context
'when logged in'
do
# The exact query count will vary depending on the 2FA settings of the
# instance, group, and user. Removing those extra 2FA queries in this case
# may not be a good idea, so we just set up the ideal case.
before
do
stub_application_setting
(
require_two_factor_authentication:
true
)
login_as
(
create
(
:user
,
:two_factor
))
end
# One each for: current user, avatar user, and upload record
it
'only performs three SQL queries'
do
get
user
.
avatar_url
# Skip queries on first application load
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
{
get
user
.
avatar_url
}.
not_to
exceed_query_limit
(
3
)
end
end
context
'when logged out'
do
# One each for avatar user and upload record
it
'only performs two SQL queries'
do
get
user
.
avatar_url
# Skip queries on first application load
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
{
get
user
.
avatar_url
}.
not_to
exceed_query_limit
(
2
)
end
end
end
spec/routing/project_routing_spec.rb
View file @
d8ccc7a0
...
...
@@ -776,10 +776,6 @@ describe 'project routing' do
it
'routes when :template_type is `issue`'
do
expect
(
get
(
show_with_template_type
(
'issue'
))).
to
route_to
(
'projects/templates#show'
,
namespace_id:
'gitlab'
,
project_id:
'gitlabhq'
,
template_type:
'issue'
,
key:
'template_name'
,
format:
'json'
)
end
it
'routes to application#route_not_found when :template_type is unknown'
do
expect
(
get
(
show_with_template_type
(
'invalid'
))).
to
route_to
(
'application#route_not_found'
,
unmatched_route:
'gitlab/gitlabhq/templates/invalid/template_name'
)
end
end
end
...
...
spec/support/controllers/sessionless_auth_controller_shared_examples.rb
View file @
d8ccc7a0
...
...
@@ -34,15 +34,8 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
context
'when the personal access token has no api scope'
,
unless:
params
[
:public
]
do
it
'does not log the user in'
do
# Several instances of where these specs are shared route the request
# through ApplicationController#route_not_found which does not involve
# the usual auth code from Devise, so does not increment the
# :user_unauthenticated_counter
#
unless
params
[
:ignore_incrementing
]
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
end
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
personal_access_token
.
update
(
scopes:
[
:read_user
])
...
...
@@ -91,15 +84,8 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
end
it
"doesn't log the user in otherwise"
,
unless:
params
[
:public
]
do
# Several instances of where these specs are shared route the request
# through ApplicationController#route_not_found which does not involve
# the usual auth code from Devise, so does not increment the
# :user_unauthenticated_counter
#
unless
params
[
:ignore_incrementing
]
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
end
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
path
,
params:
default_params
.
merge
(
private_token:
'token'
)
...
...
spec/support/shared_examples/controllers/todos_shared_examples.rb
View file @
d8ccc7a0
...
...
@@ -39,7 +39,7 @@ shared_examples 'todos actions' do
post_create
end
.
to
change
{
user
.
todos
.
count
}.
by
(
0
)
expect
(
response
).
to
have_gitlab_http_status
(
302
)
expect
(
response
).
to
have_gitlab_http_status
(
parent
.
is_a?
(
Group
)
?
401
:
302
)
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