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
170e9d24
Commit
170e9d24
authored
Sep 29, 2016
by
Rubén Dávila Santos
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '8-12-stable-ee-to-master' into 'master'
8-12-stable-ee to master See merge request !767
parents
13659833
10b404f5
Changes
77
Hide whitespace changes
Inline
Side-by-side
Showing
77 changed files
with
750 additions
and
244 deletions
+750
-244
CHANGELOG
CHANGELOG
+18
-2
CHANGELOG-EE
CHANGELOG-EE
+1
-0
GITLAB_SHELL_VERSION
GITLAB_SHELL_VERSION
+1
-1
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+5
-4
app/assets/javascripts/awards_handler.js
app/assets/javascripts/awards_handler.js
+1
-1
app/assets/javascripts/boards/components/new_list_dropdown.js.es6
...ts/javascripts/boards/components/new_list_dropdown.js.es6
+1
-2
app/assets/javascripts/create_label.js.es6
app/assets/javascripts/create_label.js.es6
+5
-4
app/assets/javascripts/diff_notes/components/resolve_btn.js.es6
...sets/javascripts/diff_notes/components/resolve_btn.js.es6
+2
-6
app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6
...ripts/diff_notes/components/resolve_discussion_btn.js.es6
+1
-5
app/assets/javascripts/diff_notes/mixins/namespace.js.es6
app/assets/javascripts/diff_notes/mixins/namespace.js.es6
+0
-9
app/assets/javascripts/diff_notes/services/resolve.js.es6
app/assets/javascripts/diff_notes/services/resolve.js.es6
+13
-13
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+13
-3
app/assets/javascripts/lib/utils/url_utility.js
app/assets/javascripts/lib/utils/url_utility.js
+1
-1
app/assets/javascripts/notes.js
app/assets/javascripts/notes.js
+4
-7
app/controllers/jwt_controller.rb
app/controllers/jwt_controller.rb
+16
-5
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+1
-1
app/controllers/projects/labels_controller.rb
app/controllers/projects/labels_controller.rb
+8
-2
app/controllers/users_controller.rb
app/controllers/users_controller.rb
+1
-1
app/mailers/notify.rb
app/mailers/notify.rb
+1
-1
app/models/concerns/elastic/application_search.rb
app/models/concerns/elastic/application_search.rb
+12
-10
app/models/concerns/elastic/issues_search.rb
app/models/concerns/elastic/issues_search.rb
+1
-1
app/models/concerns/elastic/merge_requests_search.rb
app/models/concerns/elastic/merge_requests_search.rb
+1
-1
app/models/concerns/elastic/milestones_search.rb
app/models/concerns/elastic/milestones_search.rb
+1
-1
app/models/concerns/elastic/notes_search.rb
app/models/concerns/elastic/notes_search.rb
+1
-1
app/models/concerns/elastic/projects_search.rb
app/models/concerns/elastic/projects_search.rb
+2
-2
app/models/cycle_analytics/summary.rb
app/models/cycle_analytics/summary.rb
+23
-5
app/services/auth/container_registry_authentication_service.rb
...ervices/auth/container_registry_authentication_service.rb
+9
-2
app/services/projects/create_service.rb
app/services/projects/create_service.rb
+12
-0
app/services/projects/fork_service.rb
app/services/projects/fork_service.rb
+2
-0
app/views/ci/lints/_create.html.haml
app/views/ci/lints/_create.html.haml
+1
-2
app/views/discussions/_resolve_all.html.haml
app/views/discussions/_resolve_all.html.haml
+2
-3
app/views/projects/commit/_pipelines_list.haml
app/views/projects/commit/_pipelines_list.haml
+1
-7
app/views/projects/merge_requests/_discussion.html.haml
app/views/projects/merge_requests/_discussion.html.haml
+1
-1
app/views/projects/merge_requests/show/_versions.html.haml
app/views/projects/merge_requests/show/_versions.html.haml
+5
-5
app/views/projects/notes/_note.html.haml
app/views/projects/notes/_note.html.haml
+3
-5
app/views/shared/issuable/_filter.html.haml
app/views/shared/issuable/_filter.html.haml
+1
-1
app/views/shared/issuable/_label_dropdown.html.haml
app/views/shared/issuable/_label_dropdown.html.haml
+1
-1
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+1
-1
app/views/snippets/_snippets.html.haml
app/views/snippets/_snippets.html.haml
+3
-1
config/application.rb
config/application.rb
+13
-2
features/steps/project/fork.rb
features/steps/project/fork.rb
+1
-0
lib/api/helpers.rb
lib/api/helpers.rb
+4
-1
lib/api/internal.rb
lib/api/internal.rb
+1
-1
lib/gitlab/auth.rb
lib/gitlab/auth.rb
+1
-1
lib/gitlab/elastic/search_results.rb
lib/gitlab/elastic/search_results.rb
+20
-35
lib/gitlab/import_export/import_export.yml
lib/gitlab/import_export/import_export.yml
+3
-3
lib/gitlab/import_export/project_tree_restorer.rb
lib/gitlab/import_export/project_tree_restorer.rb
+7
-1
lib/gitlab/lfs_token.rb
lib/gitlab/lfs_token.rb
+9
-10
spec/controllers/users_controller_spec.rb
spec/controllers/users_controller_spec.rb
+2
-2
spec/features/boards/boards_spec.rb
spec/features/boards/boards_spec.rb
+30
-1
spec/features/dashboard/snippets_spec.rb
spec/features/dashboard/snippets_spec.rb
+15
-0
spec/features/issues_spec.rb
spec/features/issues_spec.rb
+18
-0
spec/features/projects/snippets_spec.rb
spec/features/projects/snippets_spec.rb
+14
-0
spec/features/snippets_spec.rb
spec/features/snippets_spec.rb
+14
-0
spec/features/unsubscribe_links_spec.rb
spec/features/unsubscribe_links_spec.rb
+1
-1
spec/features/users/snippets_spec.rb
spec/features/users/snippets_spec.rb
+4
-18
spec/helpers/projects_helper_spec.rb
spec/helpers/projects_helper_spec.rb
+1
-1
spec/javascripts/labels_issue_sidebar_spec.js.es6
spec/javascripts/labels_issue_sidebar_spec.js.es6
+6
-7
spec/lib/gitlab/auth_spec.rb
spec/lib/gitlab/auth_spec.rb
+2
-2
spec/lib/gitlab/elastic/search_results_spec.rb
spec/lib/gitlab/elastic/search_results_spec.rb
+190
-4
spec/lib/gitlab/import_export/project.json
spec/lib/gitlab/import_export/project.json
+37
-1
spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+6
-0
spec/lib/gitlab/lfs_token_spec.rb
spec/lib/gitlab/lfs_token_spec.rb
+4
-4
spec/mailers/shared/notify.rb
spec/mailers/shared/notify.rb
+2
-1
spec/models/concerns/elastic/project_spec.rb
spec/models/concerns/elastic/project_spec.rb
+4
-4
spec/models/cycle_analytics/summary_spec.rb
spec/models/cycle_analytics/summary_spec.rb
+6
-0
spec/models/forked_project_link_spec.rb
spec/models/forked_project_link_spec.rb
+1
-0
spec/requests/api/api_helpers_spec.rb
spec/requests/api/api_helpers_spec.rb
+33
-6
spec/requests/api/fork_spec.rb
spec/requests/api/fork_spec.rb
+1
-1
spec/requests/api/internal_spec.rb
spec/requests/api/internal_spec.rb
+2
-2
spec/requests/jwt_controller_spec.rb
spec/requests/jwt_controller_spec.rb
+2
-2
spec/requests/lfs_http_spec.rb
spec/requests/lfs_http_spec.rb
+28
-1
spec/services/projects/fork_service_spec.rb
spec/services/projects/fork_service_spec.rb
+23
-2
spec/services/system_note_service_spec.rb
spec/services/system_note_service_spec.rb
+1
-1
spec/support/cycle_analytics_helpers.rb
spec/support/cycle_analytics_helpers.rb
+15
-11
spec/support/snippets_shared_examples.rb
spec/support/snippets_shared_examples.rb
+18
-0
spec/views/ci/lints/show.html.haml_spec.rb
spec/views/ci/lints/show.html.haml_spec.rb
+35
-0
No files found.
CHANGELOG
View file @
170e9d24
...
...
@@ -3,9 +3,25 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.13.0 (unreleased)
- Speed-up group milestones show page
v 8.12.2 (unreleased)
v 8.12.4 (unreleased)
v 8.12.3
- Update Gitlab Shell to support low IO priority for storage moves
v 8.12.2
- Fix Import/Export not recognising correctly the imported services.
- Fix prevent_secrets checkbox on admin view
- Fix snippets pagination
- Fix List-Unsubscribe header in emails
- Fix IssuesController#show degradation including project on loaded notes
- Fix an issue with the "Commits" section of the cycle analytics summary. !6513
- Fix errors importing project feature and milestone models using GitLab project import
- Make JWT messages Docker-compatible
- Fix an issue with the "Commits" section of the cycle analytics summary. !6513
- Fix duplicate branch entry in the merge request version compare dropdown
- Respect the fork_project permission when forking projects
- Only update issuable labels if they have been changed
- Fix bug where 'Search results' repeated many times when a search in the emoji search form is cleared (Xavier Bick) (@zeiv)
- Fix resolve discussion buttons endpoint path
v 8.12.1
- Fix a memory leak in HTML::Pipeline::SanitizationFilter::WHITELIST
...
...
CHANGELOG-EE
View file @
170e9d24
...
...
@@ -13,6 +13,7 @@ v 8.12.2
v 8.12.1
- Prevent secrets to be pushed to the repository
- Prevent secrets to be pushed to the repository
v 8.12.0
- Include more data in EE usage ping
...
...
GITLAB_SHELL_VERSION
View file @
170e9d24
3.6.
0
3.6.
1
app/assets/javascripts/api.js
View file @
170e9d24
...
...
@@ -5,7 +5,7 @@
namespacesPath
:
"
/api/:version/namespaces.json
"
,
groupProjectsPath
:
"
/api/:version/groups/:id/projects.json
"
,
projectsPath
:
"
/api/:version/projects.json?simple=true
"
,
labelsPath
:
"
/
api/:version/projects/:id
/labels
"
,
labelsPath
:
"
/
:namespace_path/:project_path
/labels
"
,
licensePath
:
"
/api/:version/licenses/:key
"
,
gitignorePath
:
"
/api/:version/gitignores/:key
"
,
ldapGroupsPath
:
"
/api/:version/ldap/:provider/groups.json
"
,
...
...
@@ -66,13 +66,14 @@
return
callback
(
projects
);
});
},
newLabel
:
function
(
project_id
,
data
,
callback
)
{
newLabel
:
function
(
namespace_path
,
project_path
,
data
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
labelsPath
)
.
replace
(
'
:id
'
,
project_id
);
.
replace
(
'
:namespace_path
'
,
namespace_path
)
.
replace
(
'
:project_path
'
,
project_path
);
return
$
.
ajax
({
url
:
url
,
type
:
"
POST
"
,
data
:
data
,
data
:
{
'
label
'
:
data
}
,
dataType
:
"
json
"
}).
done
(
function
(
label
)
{
return
callback
(
label
);
...
...
app/assets/javascripts/awards_handler.js
View file @
170e9d24
...
...
@@ -357,7 +357,7 @@
$
(
'
ul.emoji-menu-search, h5.emoji-search
'
).
remove
();
if
(
term
)
{
// Generate a search result block
h5
=
$
(
'
<h5>
'
).
text
(
'
Search results
'
);
h5
=
$
(
'
<h5
class="emoji-search" /
>
'
).
text
(
'
Search results
'
);
found_emojis
=
_this
.
searchEmojis
(
term
).
show
();
ul
=
$
(
'
<ul>
'
).
addClass
(
'
emoji-menu-list emoji-menu-search
'
).
append
(
found_emojis
);
$
(
'
.emoji-menu-content ul, .emoji-menu-content h5
'
).
hide
();
...
...
app/assets/javascripts/boards/components/new_list_dropdown.js.es6
View file @
170e9d24
...
...
@@ -3,8 +3,7 @@ $(() => {
$('.js-new-board-list').each(function () {
const $this = $(this);
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('project-id'));
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path'));
$this.glDropdown({
data(term, callback) {
...
...
app/assets/javascripts/create_label.js.es6
View file @
170e9d24
(function (w) {
class CreateLabelDropdown {
constructor ($el,
projectId
) {
constructor ($el,
namespacePath, projectPath
) {
this.$el = $el;
this.projectId = projectId;
this.namespacePath = namespacePath;
this.projectPath = projectPath;
this.$dropdownBack = $('.dropdown-menu-back', this.$el.closest('.dropdown'));
this.$cancelButton = $('.js-cancel-label-btn', this.$el);
this.$newLabelField = $('#new_label_name', this.$el);
...
...
@@ -91,8 +92,8 @@
e.preventDefault();
e.stopPropagation();
Api.newLabel(this.
projectId
, {
nam
e: this.$newLabelField.val(),
Api.newLabel(this.
namespacePath, this.projectPath
, {
titl
e: this.$newLabelField.val(),
color: this.$newColorField.val()
}, (label) => {
this.$newLabelCreateButton.enable();
...
...
app/assets/javascripts/diff_notes/components/resolve_btn.js.es6
View file @
170e9d24
((w) => {
w.ResolveBtn = Vue.extend({
mixins: [
ButtonMixins
],
props: {
noteId: Number,
discussionId: String,
resolved: Boolean,
namespacePath: String,
projectPath: String,
canResolve: Boolean,
resolvedBy: String
...
...
@@ -69,10 +65,10 @@
if (this.isResolved) {
promise = ResolveService
.unresolve(this.
namespace
, this.noteId);
.unresolve(this.
projectPath
, this.noteId);
} else {
promise = ResolveService
.resolve(this.
namespace
, this.noteId);
.resolve(this.
projectPath
, this.noteId);
}
promise.then((response) => {
...
...
app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js.es6
View file @
170e9d24
((w) => {
w.ResolveDiscussionBtn = Vue.extend({
mixins: [
ButtonMixins
],
props: {
discussionId: String,
mergeRequestId: Number,
namespacePath: String,
projectPath: String,
canResolve: Boolean,
},
...
...
@@ -50,7 +46,7 @@
},
methods: {
resolve: function () {
ResolveService.toggleResolveForDiscussion(this.
namespace
, this.mergeRequestId, this.discussionId);
ResolveService.toggleResolveForDiscussion(this.
projectPath
, this.mergeRequestId, this.discussionId);
}
},
created: function () {
...
...
app/assets/javascripts/diff_notes/mixins/namespace.js.es6
deleted
100644 → 0
View file @
13659833
((w) => {
w.ButtonMixins = {
computed: {
namespace: function () {
return `${this.namespacePath}/${this.projectPath}`;
}
}
};
})(window);
app/assets/javascripts/diff_notes/services/resolve.js.es6
View file @
170e9d24
...
...
@@ -9,32 +9,32 @@
Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken();
}
prepareRequest(
namespace
) {
prepareRequest(
root
) {
this.setCSRF();
Vue.http.options.root =
`/${namespace}`
;
Vue.http.options.root =
root
;
}
resolve(
namespace
, noteId) {
this.prepareRequest(
namespace
);
resolve(
projectPath
, noteId) {
this.prepareRequest(
projectPath
);
return this.noteResource.save({ noteId }, {});
}
unresolve(
namespace
, noteId) {
this.prepareRequest(
namespace
);
unresolve(
projectPath
, noteId) {
this.prepareRequest(
projectPath
);
return this.noteResource.delete({ noteId }, {});
}
toggleResolveForDiscussion(
namespace
, mergeRequestId, discussionId) {
toggleResolveForDiscussion(
projectPath
, mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId],
isResolved = discussion.isResolved();
let promise;
if (isResolved) {
promise = this.unResolveAll(
namespace
, mergeRequestId, discussionId);
promise = this.unResolveAll(
projectPath
, mergeRequestId, discussionId);
} else {
promise = this.resolveAll(
namespace
, mergeRequestId, discussionId);
promise = this.resolveAll(
projectPath
, mergeRequestId, discussionId);
}
promise.then((response) => {
...
...
@@ -57,10 +57,10 @@
})
}
resolveAll(
namespace
, mergeRequestId, discussionId) {
resolveAll(
projectPath
, mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(
namespace
);
this.prepareRequest(
projectPath
);
discussion.loading = true;
...
...
@@ -70,10 +70,10 @@
}, {});
}
unResolveAll(
namespace
, mergeRequestId, discussionId) {
unResolveAll(
projectPath
, mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(
namespace
);
this.prepareRequest(
projectPath
);
discussion.loading = true;
...
...
app/assets/javascripts/labels_select.js
View file @
170e9d24
...
...
@@ -4,9 +4,10 @@
var
_this
;
_this
=
this
;
$
(
'
.js-label-select
'
).
each
(
function
(
i
,
dropdown
)
{
var
$block
,
$colorPreview
,
$dropdown
,
$form
,
$loading
,
$selectbox
,
$sidebarCollapsedValue
,
$value
,
abilityName
,
defaultLabel
,
enableLabelCreateButton
,
issueURLSplit
,
issueUpdateURL
,
labelHTMLTemplate
,
labelNoneHTMLTemplate
,
labelUrl
,
projectId
,
saveLabelData
,
selectedLabel
,
showAny
,
showNo
,
$sidebarLabelTooltip
;
var
$block
,
$colorPreview
,
$dropdown
,
$form
,
$loading
,
$selectbox
,
$sidebarCollapsedValue
,
$value
,
abilityName
,
defaultLabel
,
enableLabelCreateButton
,
issueURLSplit
,
issueUpdateURL
,
labelHTMLTemplate
,
labelNoneHTMLTemplate
,
labelUrl
,
namespacePath
,
projectPath
,
saveLabelData
,
selectedLabel
,
showAny
,
showNo
,
$sidebarLabelTooltip
,
initialSelected
;
$dropdown
=
$
(
dropdown
);
projectId
=
$dropdown
.
data
(
'
project-id
'
);
namespacePath
=
$dropdown
.
data
(
'
namespace-path
'
);
projectPath
=
$dropdown
.
data
(
'
project-path
'
);
labelUrl
=
$dropdown
.
data
(
'
labels
'
);
issueUpdateURL
=
$dropdown
.
data
(
'
issueUpdate
'
);
selectedLabel
=
$dropdown
.
data
(
'
selected
'
);
...
...
@@ -24,6 +25,11 @@
$sidebarLabelTooltip
=
$block
.
find
(
'
.js-sidebar-labels-tooltip
'
);
$value
=
$block
.
find
(
'
.value
'
);
$loading
=
$block
.
find
(
'
.block-loading
'
).
fadeOut
();
initialSelected
=
$selectbox
.
find
(
'
input[name="
'
+
$dropdown
.
data
(
'
field-name
'
)
+
'
"]
'
)
.
map
(
function
()
{
return
this
.
value
;
}).
get
();
if
(
issueUpdateURL
!=
null
)
{
issueURLSplit
=
issueUpdateURL
.
split
(
'
/
'
);
}
...
...
@@ -35,7 +41,7 @@
$sidebarLabelTooltip
.
tooltip
();
if
(
$dropdown
.
closest
(
'
.dropdown
'
).
find
(
'
.dropdown-new-label
'
).
length
)
{
new
gl
.
CreateLabelDropdown
(
$dropdown
.
closest
(
'
.dropdown
'
).
find
(
'
.dropdown-new-label
'
),
projectId
);
new
gl
.
CreateLabelDropdown
(
$dropdown
.
closest
(
'
.dropdown
'
).
find
(
'
.dropdown-new-label
'
),
namespacePath
,
projectPath
);
}
saveLabelData
=
function
()
{
...
...
@@ -43,6 +49,10 @@
selected
=
$dropdown
.
closest
(
'
.selectbox
'
).
find
(
"
input[name='
"
+
(
$dropdown
.
data
(
'
field-name
'
))
+
"
']
"
).
map
(
function
()
{
return
this
.
value
;
}).
get
();
if
(
_
.
isEqual
(
initialSelected
,
selected
))
return
;
initialSelected
=
selected
;
data
=
{};
data
[
abilityName
]
=
{};
data
[
abilityName
].
label_ids
=
selected
;
...
...
app/assets/javascripts/lib/utils/url_utility.js
View file @
170e9d24
...
...
@@ -19,7 +19,7 @@
while
(
i
<
sURLVariables
.
length
)
{
sParameterName
=
sURLVariables
[
i
].
split
(
'
=
'
);
if
(
sParameterName
[
0
]
===
sParam
)
{
values
.
push
(
sParameterName
[
1
]);
values
.
push
(
sParameterName
[
1
]
.
replace
(
/
\+
/g
,
'
'
)
);
}
i
++
;
}
...
...
app/assets/javascripts/notes.js
View file @
170e9d24
...
...
@@ -432,14 +432,12 @@
var
$form
=
$
(
xhr
.
target
);
if
(
$form
.
attr
(
'
data-resolve-all
'
)
!=
null
)
{
var
namespacePath
=
$form
.
attr
(
'
data-namespace-path
'
),
projectPath
=
$form
.
attr
(
'
data-project-path
'
)
discussionId
=
$form
.
attr
(
'
data-discussion-id
'
),
mergeRequestId
=
$form
.
attr
(
'
data-noteable-iid
'
),
namespace
=
namespacePath
+
'
/
'
+
projectPath
;
var
projectPath
=
$form
.
data
(
'
project-path
'
)
discussionId
=
$form
.
data
(
'
discussion-id
'
),
mergeRequestId
=
$form
.
data
(
'
noteable-iid
'
);
if
(
ResolveService
!=
null
)
{
ResolveService
.
toggleResolveForDiscussion
(
namespace
,
mergeRequestId
,
discussionId
);
ResolveService
.
toggleResolveForDiscussion
(
projectPath
,
mergeRequestId
,
discussionId
);
}
}
...
...
@@ -854,7 +852,6 @@
.
closest
(
'
form
'
)
.
attr
(
'
data-discussion-id
'
,
discussionId
)
.
attr
(
'
data-resolve-all
'
,
'
true
'
)
.
attr
(
'
data-namespace-path
'
,
$this
.
attr
(
'
data-namespace-path
'
))
.
attr
(
'
data-project-path
'
,
$this
.
attr
(
'
data-project-path
'
));
};
...
...
app/controllers/jwt_controller.rb
View file @
170e9d24
...
...
@@ -25,7 +25,7 @@ class JwtController < ApplicationController
authenticate_with_http_basic
do
|
login
,
password
|
@authentication_result
=
Gitlab
::
Auth
.
find_for_git_client
(
login
,
password
,
project:
nil
,
ip:
request
.
ip
)
render_
403
unless
@authentication_result
.
success?
&&
render_
unauthorized
unless
@authentication_result
.
success?
&&
(
@authentication_result
.
actor
.
nil?
||
@authentication_result
.
actor
.
is_a?
(
User
))
end
rescue
Gitlab
::
Auth
::
MissingPersonalTokenError
...
...
@@ -33,10 +33,21 @@ class JwtController < ApplicationController
end
def
render_missing_personal_token
render
plain:
"HTTP Basic: Access denied
\n
"
\
"You have 2FA enabled, please use a personal access token for Git over HTTP.
\n
"
\
"You can generate one at
#{
profile_personal_access_tokens_url
}
"
,
status:
401
render
json:
{
errors:
[
{
code:
'UNAUTHORIZED'
,
message:
"HTTP Basic: Access denied
\n
"
\
"You have 2FA enabled, please use a personal access token for Git over HTTP.
\n
"
\
"You can generate one at
#{
profile_personal_access_tokens_url
}
"
}
]
},
status:
401
end
def
render_unauthorized
render
json:
{
errors:
[
{
code:
'UNAUTHORIZED'
,
message:
'HTTP Basic: Access denied'
}
]
},
status:
401
end
def
auth_params
...
...
app/controllers/projects/issues_controller.rb
View file @
170e9d24
...
...
@@ -60,7 +60,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def
show
raw_notes
=
@issue
.
notes
_with_associations
.
fresh
raw_notes
=
@issue
.
notes
.
inc_relations_for_view
.
fresh
@notes
=
Banzai
::
NoteRenderer
.
render
(
raw_notes
,
@project
,
current_user
,
@path
,
@project_wiki
,
@ref
)
...
...
app/controllers/projects/labels_controller.rb
View file @
170e9d24
...
...
@@ -30,9 +30,15 @@ class Projects::LabelsController < Projects::ApplicationController
@label
=
@project
.
labels
.
create
(
label_params
)
if
@label
.
valid?
redirect_to
namespace_project_labels_path
(
@project
.
namespace
,
@project
)
respond_to
do
|
format
|
format
.
html
{
redirect_to
namespace_project_labels_path
(
@project
.
namespace
,
@project
)
}
format
.
json
{
render
json:
@label
}
end
else
render
'new'
respond_to
do
|
format
|
format
.
html
{
render
'new'
}
format
.
json
{
render
json:
{
message:
@label
.
errors
.
messages
},
status:
400
}
end
end
end
...
...
app/controllers/users_controller.rb
View file @
170e9d24
...
...
@@ -65,7 +65,7 @@ class UsersController < ApplicationController
format
.
html
{
render
'show'
}
format
.
json
do
render
json:
{
html:
view_to_html_string
(
"snippets/_snippets"
,
collection:
@snippets
)
html:
view_to_html_string
(
"snippets/_snippets"
,
collection:
@snippets
,
remote:
true
)
}
end
end
...
...
app/mailers/notify.rb
View file @
170e9d24
...
...
@@ -110,7 +110,7 @@ class Notify < BaseMailer
headers
[
'X-GitLab-Reply-Key'
]
=
reply_key
if
!
@labels_url
&&
@sent_notification
&&
@sent_notification
.
unsubscribable?
headers
[
'List-Unsubscribe'
]
=
unsubscribe_sent_notification_url
(
@sent_notification
,
force:
true
)
headers
[
'List-Unsubscribe'
]
=
"<
#{
unsubscribe_sent_notification_url
(
@sent_notification
,
force:
true
)
}
>"
@sent_notification_url
=
unsubscribe_sent_notification_url
(
@sent_notification
)
end
...
...
app/models/concerns/elastic/application_search.rb
View file @
170e9d24
...
...
@@ -147,9 +147,13 @@ module Elastic
}
end
def
project_ids_filter
(
query_hash
,
project_ids
,
public_and_internal_projects
=
true
)
if
project_ids
condition
=
project_ids_condition
(
project_ids
,
public_and_internal_projects
)
def
project_ids_filter
(
query_hash
,
options
)
if
options
[
:project_ids
]
condition
=
project_ids_condition
(
options
[
:current_user
],
options
[
:project_ids
],
options
[
:public_and_internal_projects
]
)
query_hash
[
:query
][
:bool
][
:filter
]
=
{
has_parent:
{
...
...
@@ -166,19 +170,17 @@ module Elastic
query_hash
end
def
project_ids_condition
(
project_ids
,
public_and_internal_projects
)
def
project_ids_condition
(
current_user
,
project_ids
,
public_and_internal_projects
)
conditions
=
[{
terms:
{
id:
project_ids
}
}]
if
public_and_internal_projects
conditions
<<
{
term:
{
visibility_level:
Project
::
PUBLIC
}
}
conditions
<<
{
term:
{
visibility_level:
Project
::
PUBLIC
}
}
conditions
<<
{
term:
{
visibility_level:
Project
::
INTERNAL
}
}
if
current_user
conditions
<<
{
term:
{
visibility_level:
Project
::
INTERNAL
}
}
end
end
conditions
...
...
app/models/concerns/elastic/issues_search.rb
View file @
170e9d24
...
...
@@ -44,7 +44,7 @@ module Elastic
query_hash
=
basic_query_hash
(
%w(title^2 description)
,
query
)
end
query_hash
=
project_ids_filter
(
query_hash
,
options
[
:project_ids
],
options
[
:public_and_internal_projects
]
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
query_hash
=
confidentiality_filter
(
query_hash
,
options
[
:current_user
])
self
.
__elasticsearch__
.
search
(
query_hash
)
...
...
app/models/concerns/elastic/merge_requests_search.rb
View file @
170e9d24
...
...
@@ -66,7 +66,7 @@ module Elastic
query_hash
=
basic_query_hash
(
%w(title^2 description)
,
query
)
end
query_hash
=
project_ids_filter
(
query_hash
,
options
[
:project_ids
],
options
[
:public_and_internal_projects
]
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
self
.
__elasticsearch__
.
search
(
query_hash
)
end
...
...
app/models/concerns/elastic/milestones_search.rb
View file @
170e9d24
...
...
@@ -31,7 +31,7 @@ module Elastic
query_hash
=
basic_query_hash
(
options
[
:in
],
query
)
query_hash
=
project_ids_filter
(
query_hash
,
options
[
:project_ids
],
options
[
:public_and_internal_projects
]
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
self
.
__elasticsearch__
.
search
(
query_hash
)
end
...
...
app/models/concerns/elastic/notes_search.rb
View file @
170e9d24
...
...
@@ -60,7 +60,7 @@ module Elastic
query_hash
[
:track_scores
]
=
true
end
query_hash
=
project_ids_filter
(
query_hash
,
options
[
:project_ids
],
options
[
:public_and_internal_projects
]
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
query_hash
=
confidentiality_filter
(
query_hash
,
options
[
:current_user
])
query_hash
[
:sort
]
=
[
...
...
app/models/concerns/elastic/projects_search.rb
View file @
170e9d24
...
...
@@ -83,10 +83,10 @@ module Elastic
}
end
if
options
[
:pids
]
if
options
[
:p
roject_
ids
]
filters
<<
{
bool:
{
should:
project_ids_condition
(
options
[
:
p
ids
],
options
[
:public_and_internal_projects
])
should:
project_ids_condition
(
options
[
:
current_user
],
options
[
:project_
ids
],
options
[
:public_and_internal_projects
])
}
}
end
...
...
app/models/cycle_analytics/summary.rb
View file @
170e9d24
...
...
@@ -10,15 +10,33 @@ class CycleAnalytics
end
def
commits
repository
=
@project
.
repository
.
raw_repository
if
@project
.
default_branch
repository
.
log
(
ref:
@project
.
default_branch
,
after:
@from
).
count
end
ref
=
@project
.
default_branch
.
presence
count_commits_for
(
ref
)
end
def
deploys
@project
.
deployments
.
where
(
"created_at > ?"
,
@from
).
count
end
private
# Don't use the `Gitlab::Git::Repository#log` method, because it enforces
# a limit. Since we need a commit count, we _can't_ enforce a limit, so
# the easiest way forward is to replicate the relevant portions of the
# `log` function here.
def
count_commits_for
(
ref
)
return
unless
ref
repository
=
@project
.
repository
.
raw_repository
sha
=
@project
.
repository
.
commit
(
ref
).
sha
cmd
=
%W(git --git-dir=
#{
repository
.
path
}
log)
cmd
<<
'--format=%H'
cmd
<<
"--after=
#{
@from
.
iso8601
}
"
cmd
<<
sha
raw_output
=
IO
.
popen
(
cmd
)
{
|
io
|
io
.
read
}
raw_output
.
lines
.
count
end
end
end
app/services/auth/container_registry_authentication_service.rb
View file @
170e9d24
...
...
@@ -7,10 +7,10 @@ module Auth
def
execute
(
authentication_abilities
:)
@authentication_abilities
=
authentication_abilities
return
error
(
'
not found'
,
404
)
unless
registry
.
enabled
return
error
(
'
UNAVAILABLE'
,
status:
404
,
message:
'registry not enabled'
)
unless
registry
.
enabled
unless
current_user
||
project
return
error
(
'
forbidden'
,
403
)
unless
scope
return
error
(
'
DENIED'
,
status:
403
,
message:
'access forbidden'
)
unless
scope
end
{
token:
authorized_token
(
scope
).
encoded
}
...
...
@@ -111,5 +111,12 @@ module Auth
@authentication_abilities
.
include?
(
:create_container_image
)
&&
can?
(
current_user
,
:create_container_image
,
requested_project
)
end
def
error
(
code
,
status
:,
message:
''
)
{
errors:
[{
code:
code
,
message:
message
}],
http_status:
status
}
end
end
end
app/services/projects/create_service.rb
View file @
170e9d24
...
...
@@ -15,6 +15,11 @@ module Projects
return
@project
end
unless
allowed_fork?
(
forked_from_project_id
)
@project
.
errors
.
add
(
:forked_from_project_id
,
'is forbidden'
)
return
@project
end
# Set project name from path
if
@project
.
name
.
present?
&&
@project
.
path
.
present?
# if both name and path set - everything is ok
...
...
@@ -71,6 +76,13 @@ module Projects
@project
.
errors
.
add
(
:namespace
,
"is not valid"
)
end
def
allowed_fork?
(
source_project_id
)
return
true
if
source_project_id
.
nil?
source_project
=
Project
.
find_by
(
id:
source_project_id
)
current_user
.
can?
(
:fork_project
,
source_project
)
end
def
allowed_namespace?
(
user
,
namespace_id
)
namespace
=
Namespace
.
find_by
(
id:
namespace_id
)
current_user
.
can?
(
:create_projects
,
namespace
)
...
...
app/services/projects/fork_service.rb
View file @
170e9d24
...
...
@@ -16,6 +16,8 @@ module Projects
end
new_project
=
CreateService
.
new
(
current_user
,
new_params
).
execute
return
new_project
unless
new_project
.
persisted?
builds_access_level
=
@project
.
project_feature
.
builds_access_level
new_project
.
project_feature
.
update_attributes
(
builds_access_level:
builds_access_level
)
...
...
app/views/ci/lints/_create.html.haml
View file @
170e9d24
...
...
@@ -16,8 +16,7 @@
%tr
%td
#{
stage
.
capitalize
}
Job -
#{
build
[
:name
]
}
%td
%pre
=
simple_format
build
[
:commands
]
%pre
=
build
[
:commands
]
%br
%b
Tag list:
...
...
app/views/discussions/_resolve_all.html.haml
View file @
170e9d24
-
if
discussion
.
for_merge_request?
%resolve-discussion-btn
{
":namespace-path"
=>
"'#{discussion.project.namespace.path}'"
,
":project-path"
=>
"'#{discussion.project.path}'"
,
%resolve-discussion-btn
{
":project-path"
=>
"'#{project_path(discussion.project)}'"
,
":discussion-id"
=>
"'#{discussion.id}'"
,
":merge-request-id"
=>
discussion
.
noteable
.
iid
,
":can-resolve"
=>
discussion
.
can_resolve?
(
current_user
),
"inline-template"
=>
true
}
.btn-group
{
role:
"group"
,
"v-if"
=>
"showButton"
}
%button
.btn.btn-default
{
type:
"button"
,
"@click"
=>
"resolve"
,
":disabled"
=>
"loading"
}
%button
.btn.btn-default
{
type:
"button"
,
"@click"
=>
"resolve"
,
":disabled"
=>
"loading"
,
"v-cloak"
=>
"true"
}
=
icon
(
"spinner spin"
,
"v-show"
=>
"loading"
)
{{ buttonText }}
app/views/projects/commit/_pipelines_list.haml
View file @
170e9d24
...
...
@@ -8,13 +8,7 @@
%tbody
%th
Status
%th
Commit
-
pipelines
.
stages
.
each
do
|
stage
|
%th
.stage
-
if
stage
.
titleize
.
length
>
12
%span
.has-tooltip
{
title:
"#{stage.titleize}"
}
=
stage
.
titleize
-
else
=
stage
.
titleize
%th
Stages
%th
%th
=
render
pipelines
,
commit_sha:
true
,
stage:
true
,
allow_retry:
true
,
stages:
pipelines
.
stages
,
status_icon_only:
true
,
hide_branch:
true
app/views/projects/merge_requests/_discussion.html.haml
View file @
170e9d24
...
...
@@ -5,7 +5,7 @@
-
if
@merge_request
.
reopenable?
=
link_to
'Reopen merge request'
,
merge_request_path
(
@merge_request
,
merge_request:
{
state_event: :reopen
}),
method: :put
,
class:
"btn btn-nr btn-comment btn-reopen reopen-mr-link js-note-target-reopen"
,
title:
"Reopen merge request"
,
data:
{
original_text:
"Reopen merge request"
,
alternative_text:
"Comment & reopen merge request"
}
%comment-and-resolve-btn
{
"inline-template"
=>
true
,
":discussion-id"
=>
""
}
%button
.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button
{
"v-if"
=>
"showButton"
,
type:
"submit"
,
data:
{
namespace_path:
"#{@merge_request.project.namespace.path}"
,
project_path:
"#{@merge_request.project.path
}"
}
}
%button
.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button
{
"v-if"
=>
"showButton"
,
type:
"submit"
,
data:
{
project_path:
"#{project_path(@merge_request.project)
}"
}
}
{{ buttonText }}
#notes
=
render
"projects/notes/notes_with_form"
app/views/projects/merge_requests/show/_versions.html.haml
View file @
170e9d24
...
...
@@ -58,11 +58,11 @@
.monospace
#{
short_sha
(
merge_request_diff
.
head_commit_sha
)
}
%small
=
time_ago_with_tooltip
(
merge_request_diff
.
created_at
)
%li
=
link_to
merge_request_version_path
(
@project
,
@merge_request
,
@merge_request_diff
),
class:
(
'is-active'
unless
@start_sha
)
do
%strong
#{
@merge_request
.
target_branch
}
(base)
.monospace
#{
short_sha
(
@merge_request_diff
.
base_commit_sha
)
}
%li
=
link_to
merge_request_version_path
(
@project
,
@merge_request
,
@merge_request_diff
),
class:
(
'is-active'
unless
@start_sha
)
do
%strong
#{
@merge_request
.
target_branch
}
(base)
.monospace
#{
short_sha
(
@merge_request_diff
.
base_commit_sha
)
}
-
unless
@merge_request_diff
.
latest?
&&
!
@start_sha
.comments-disabled-notif.content-block
...
...
app/views/projects/notes/_note.html.haml
View file @
170e9d24
...
...
@@ -24,14 +24,12 @@
-
if
note
.
resolvable?
-
can_resolve
=
can?
(
current_user
,
:resolve_note
,
note
)
%resolve-btn
{
":namespace-path"
=>
"'#{note.project.namespace.path}'"
,
":project-path"
=>
"'#{note.project.path}'"
,
":discussion-id"
=>
"'#{note.discussion_id}'"
,
%resolve-btn
{
"project-path"
=>
"#{project_path(note.project)}"
,
"discussion-id"
=>
"#{note.discussion_id}"
,
":note-id"
=>
note
.
id
,
":resolved"
=>
note
.
resolved?
,
":can-resolve"
=>
can_resolve
,
"
:resolved-by"
=>
"'#{note.resolved_by.try(:name)}'
"
,
"
resolved-by"
=>
"#{note.resolved_by.try(:name)}
"
,
"v-show"
=>
"#{can_resolve || note.resolved?}"
,
"inline-template"
=>
true
,
"v-ref:note_#{note.id}"
=>
true
}
...
...
app/views/shared/issuable/_filter.html.haml
View file @
170e9d24
...
...
@@ -49,7 +49,7 @@
%input
.pull-left.form-control
{
type:
"search"
,
placeholder:
"Filter by name..."
,
"v-model"
=>
"filters.search"
,
"debounce"
=>
"250"
}
-
if
can?
(
current_user
,
:admin_list
,
@project
)
.dropdown.pull-right
%button
.btn.btn-create.js-new-board-list
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
labels:
labels_filter_path
,
project_id:
@project
.
try
(
:id
)
}
}
%button
.btn.btn-create.js-new-board-list
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
labels:
labels_filter_path
,
namespace_path:
@project
.
try
(
:namespace
).
try
(
:path
),
project_path:
@project
.
try
(
:path
)
}
}
Create new list
.dropdown-menu.dropdown-menu-paging.dropdown-menu-align-right.dropdown-menu-issues-board-new.dropdown-menu-selectable
=
render
partial:
"shared/issuable/label_page_default"
,
locals:
{
show_footer:
true
,
show_create:
true
,
show_boards_content:
true
,
title:
"Create a new list"
}
...
...
app/views/shared/issuable/_label_dropdown.html.haml
View file @
170e9d24
...
...
@@ -4,7 +4,7 @@
-
show_footer
=
local_assigns
.
fetch
(
:show_footer
,
true
)
-
data_options
=
local_assigns
.
fetch
(
:data_options
,
{})
-
classes
=
local_assigns
.
fetch
(
:classes
,
[])
-
dropdown_data
=
{
toggle:
'dropdown'
,
field_name:
'label_name[]'
,
show_no:
"true"
,
show_any:
"true"
,
selected:
params
[
:label_name
],
project_id:
@project
.
try
(
:id
),
labels:
labels_filter_path
,
default_label:
"Label"
}
-
dropdown_data
=
{
toggle:
'dropdown'
,
field_name:
'label_name[]'
,
show_no:
"true"
,
show_any:
"true"
,
selected:
params
[
:label_name
],
namespace_path:
@project
.
try
(
:namespace
).
try
(
:path
),
project_path:
@project
.
try
(
:path
),
labels:
labels_filter_path
,
default_label:
"Label"
}
-
dropdown_data
.
merge!
(
data_options
)
-
classes
<<
'js-extra-options'
if
extra_options
-
classes
<<
'js-filter-submit'
if
filter_submit
...
...
app/views/shared/issuable/_sidebar.html.haml
View file @
170e9d24
...
...
@@ -128,7 +128,7 @@
-
issuable
.
labels_array
.
each
do
|
label
|
=
hidden_field_tag
"
#{
issuable
.
to_ability_name
}
[label_names][]"
,
label
.
id
,
id:
nil
.dropdown
%button
.dropdown-menu-toggle.js-label-select.js-multiselect
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
field_name:
"#{issuable.to_ability_name}[label_names][]"
,
ability_name:
issuable
.
to_ability_name
,
show_no:
"true"
,
show_any:
"true"
,
project_id:
(
@project
.
id
if
@project
),
issue_update:
issuable_json_path
(
issuable
),
labels:
(
namespace_project_labels_path
(
@project
.
namespace
,
@project
,
:json
)
if
@project
)}}
%button
.dropdown-menu-toggle.js-label-select.js-multiselect
{
type:
"button"
,
data:
{
toggle:
"dropdown"
,
field_name:
"#{issuable.to_ability_name}[label_names][]"
,
ability_name:
issuable
.
to_ability_name
,
show_no:
"true"
,
show_any:
"true"
,
namespace_path:
@project
.
try
(
:namespace
).
try
(
:path
),
project_path:
@project
.
try
(
:path
),
issue_update:
issuable_json_path
(
issuable
),
labels:
(
namespace_project_labels_path
(
@project
.
namespace
,
@project
,
:json
)
if
@project
)}}
%span
.dropdown-toggle-text
Label
=
icon
(
'chevron-down'
)
...
...
app/views/snippets/_snippets.html.haml
View file @
170e9d24
-
remote
=
local_assigns
.
fetch
(
:remote
,
false
)
.snippets-list-holder
%ul
.content-list
=
render
partial:
'shared/snippets/snippet'
,
collection:
@snippets
...
...
@@ -5,7 +7,7 @@
%li
.nothing-here-block
Nothing here.
=
paginate
@snippets
,
theme:
'gitlab'
,
remote:
tru
e
=
paginate
@snippets
,
theme:
'gitlab'
,
remote:
remot
e
:javascript
gl
.
SnippetsList
();
config/application.rb
View file @
170e9d24
...
...
@@ -102,13 +102,24 @@ module Gitlab
config
.
action_view
.
sanitized_allowed_protocols
=
%w(smb)
config
.
middleware
.
use
Rack
::
Attack
config
.
middleware
.
insert_before
Warden
::
Manager
,
Rack
::
Attack
# Allow access to GitLab API from other domains
config
.
middleware
.
use
Rack
::
Cors
do
config
.
middleware
.
insert_before
Warden
::
Manager
,
Rack
::
Cors
do
allow
do
origins
Gitlab
.
config
.
gitlab
.
url
resource
'/api/*'
,
credentials:
true
,
headers: :any
,
methods: :any
,
expose:
[
'Link'
]
end
# Cross-origin requests must not have the session cookie available
allow
do
origins
'*'
resource
'/api/*'
,
credentials:
false
,
headers: :any
,
methods: :any
,
expose:
[
'Link'
]
...
...
features/steps/project/fork.rb
View file @
170e9d24
...
...
@@ -70,6 +70,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
step
'There is an existent fork of the "Shop" project'
do
user
=
create
(
:user
,
name:
'Mike'
)
@project
.
team
<<
[
user
,
:reporter
]
@forked_project
=
Projects
::
ForkService
.
new
(
@project
,
user
).
execute
end
...
...
lib/api/helpers.rb
View file @
170e9d24
...
...
@@ -21,8 +21,11 @@ module API
end
# Check the Rails session for valid authentication details
#
# Until CSRF protection is added to the API, disallow this method for
# state-changing endpoints
def
find_user_from_warden
warden
?
warden
.
authenticate
:
nil
warden
.
try
(
:authenticate
)
if
request
.
get?
||
request
.
head?
end
def
find_user_by_private_token
...
...
lib/api/internal.rb
View file @
170e9d24
...
...
@@ -90,7 +90,7 @@ module API
{
username:
token_handler
.
actor_name
,
lfs_token:
token_handler
.
generate
,
lfs_token:
token_handler
.
token
,
repository_http_path:
project
.
http_url_to_repo
}
end
...
...
lib/gitlab/auth.rb
View file @
170e9d24
...
...
@@ -129,7 +129,7 @@ module Gitlab
read_authentication_abilities
end
Result
.
new
(
actor
,
nil
,
token_handler
.
type
,
authentication_abilities
)
if
Devise
.
secure_compare
(
token_handler
.
value
,
password
)
Result
.
new
(
actor
,
nil
,
token_handler
.
type
,
authentication_abilities
)
if
Devise
.
secure_compare
(
token_handler
.
token
,
password
)
end
def
build_access_token_check
(
login
,
password
)
...
...
lib/gitlab/elastic/search_results.rb
View file @
170e9d24
module
Gitlab
module
Elastic
class
SearchResults
attr_reader
:current_user
,
:query
attr_reader
:current_user
,
:query
,
:public_and_internal_projects
# Limit search results by passed project ids
# It allows us to search only for projects user has access to
...
...
@@ -59,41 +59,28 @@ module Gitlab
private
def
projects
opt
=
{
pids:
limit_project_ids
,
public_and_internal_projects:
@public_and_internal_projects
def
base_options
{
current_user:
current_user
,
project_ids:
limit_project_ids
,
public_and_internal_projects:
public_and_internal_projects
}
end
@projects
=
Project
.
elastic_search
(
query
,
options:
opt
)
def
projects
Project
.
elastic_search
(
query
,
options:
base_options
)
end
def
issues
opt
=
{
project_ids:
limit_project_ids
,
current_user:
current_user
,
public_and_internal_projects:
@public_and_internal_projects
}
Issue
.
elastic_search
(
query
,
options:
opt
)
Issue
.
elastic_search
(
query
,
options:
base_options
)
end
def
milestones
opt
=
{
project_ids:
limit_project_ids
,
public_and_internal_projects:
@public_and_internal_projects
}
Milestone
.
elastic_search
(
query
,
options:
opt
)
Milestone
.
elastic_search
(
query
,
options:
base_options
)
end
def
merge_requests
opt
=
{
project_ids:
limit_project_ids
,
public_and_internal_projects:
@public_and_internal_projects
}
MergeRequest
.
elastic_search
(
query
,
options:
opt
)
MergeRequest
.
elastic_search
(
query
,
options:
base_options
)
end
def
blobs
...
...
@@ -101,7 +88,7 @@ module Gitlab
Kaminari
.
paginate_array
([])
else
opt
=
{
additional_filter:
build_filter_by_project
(
limit_project_ids
,
@public_and_internal_projects
)
additional_filter:
build_filter_by_project
}
Repository
.
search
(
...
...
@@ -117,7 +104,7 @@ module Gitlab
Kaminari
.
paginate_array
([])
else
options
=
{
additional_filter:
build_filter_by_project
(
limit_project_ids
,
@public_and_internal_projects
)
additional_filter:
build_filter_by_project
}
Repository
.
find_commits_by_message_with_elastic
(
...
...
@@ -129,17 +116,15 @@ module Gitlab
end
end
def
build_filter_by_project
(
project_ids
,
public_and_internal_projects
)
conditions
=
[{
terms:
{
id:
project_ids
}
}]
def
build_filter_by_project
conditions
=
[{
terms:
{
id:
limit_
project_ids
}
}]
if
public_and_internal_projects
conditions
<<
{
term:
{
visibility_level:
Project
::
PUBLIC
}
}
conditions
<<
{
term:
{
visibility_level:
Project
::
PUBLIC
}
}
conditions
<<
{
term:
{
visibility_level:
Project
::
INTERNAL
}
}
if
current_user
conditions
<<
{
term:
{
visibility_level:
Project
::
INTERNAL
}
}
end
end
{
...
...
lib/gitlab/import_export/import_export.yml
View file @
170e9d24
# Model relationships to be included in the project import/export
project_tree
:
-
:labels
-
milestones
:
-
:events
-
issues
:
-
:events
-
notes
:
...
...
@@ -39,9 +42,6 @@ project_tree:
-
protected_branches
:
-
:merge_access_levels
-
:push_access_levels
-
:labels
-
milestones
:
-
:events
-
:project_feature
# Only include the following attributes for the models specified.
...
...
lib/gitlab/import_export/project_tree_restorer.rb
View file @
170e9d24
...
...
@@ -61,11 +61,17 @@ module Gitlab
def
restore_project
return
@project
unless
@tree_hash
project_params
=
@tree_hash
.
reject
{
|
_key
,
value
|
value
.
is_a?
(
Array
)
}
@project
.
update
(
project_params
)
@project
end
def
project_params
@tree_hash
.
reject
do
|
key
,
value
|
# return params that are not 1 to many or 1 to 1 relations
value
.
is_a?
(
Array
)
||
key
==
key
.
singularize
end
end
# Given a relation hash containing one or more models and its relationships,
# loops through each model and each object from a model type and
# and assigns its correspondent attributes hash from +tree_hash+
...
...
lib/gitlab/lfs_token.rb
View file @
170e9d24
...
...
@@ -17,19 +17,18 @@ module Gitlab
end
end
def
generate
token
=
Devise
.
friendly_token
(
TOKEN_LENGTH
)
def
token
Gitlab
::
Redis
.
with
do
|
redis
|
redis
.
set
(
redis_key
,
token
,
ex:
EXPIRY_TIME
)
end
token
=
redis
.
get
(
redis_key
)
token
end
if
token
redis
.
expire
(
redis_key
,
EXPIRY_TIME
)
else
token
=
Devise
.
friendly_token
(
TOKEN_LENGTH
)
redis
.
set
(
redis_key
,
token
,
ex:
EXPIRY_TIME
)
end
def
value
Gitlab
::
Redis
.
with
do
|
redis
|
redis
.
get
(
redis_key
)
token
end
end
...
...
spec/controllers/users_controller_spec.rb
View file @
170e9d24
...
...
@@ -73,8 +73,8 @@ describe UsersController do
end
context
'forked project'
do
let
!
(
:project
)
{
create
(
:project
)
}
let
!
(
:forked_project
)
{
Projects
::
ForkService
.
new
(
project
,
user
).
execute
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:forked_project
)
{
Projects
::
ForkService
.
new
(
project
,
user
).
execute
}
before
do
sign_in
(
user
)
...
...
spec/features/boards/boards_spec.rb
View file @
170e9d24
...
...
@@ -62,6 +62,7 @@ describe 'Issue Boards', feature: true, js: true do
let
(
:bug
)
{
create
(
:label
,
project:
project
,
name:
'Bug'
)
}
let!
(
:backlog
)
{
create
(
:label
,
project:
project
,
name:
'Backlog'
)
}
let!
(
:done
)
{
create
(
:label
,
project:
project
,
name:
'Done'
)
}
let!
(
:accepting
)
{
create
(
:label
,
project:
project
,
name:
'Accepting Merge Requests'
)
}
let!
(
:list1
)
{
create
(
:list
,
board:
project
.
board
,
label:
planning
,
position:
0
)
}
let!
(
:list2
)
{
create
(
:list
,
board:
project
.
board
,
label:
development
,
position:
1
)
}
...
...
@@ -75,7 +76,7 @@ describe 'Issue Boards', feature: true, js: true do
let!
(
:issue6
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
planning
,
development
])
}
let!
(
:issue7
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
development
])
}
let!
(
:issue8
)
{
create
(
:closed_issue
,
project:
project
)
}
let!
(
:issue9
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
testing
,
bug
])
}
let!
(
:issue9
)
{
create
(
:labeled_issue
,
project:
project
,
labels:
[
testing
,
bug
,
accepting
])
}
before
do
visit
namespace_project_board_path
(
project
.
namespace
,
project
)
...
...
@@ -441,6 +442,34 @@ describe 'Issue Boards', feature: true, js: true do
wait_for_empty_boards
((
2
..
4
))
end
it
'filters by label with space after reload'
do
page
.
within
'.issues-filters'
do
click_button
(
'Label'
)
wait_for_ajax
page
.
within
'.dropdown-menu-labels'
do
click_link
(
accepting
.
title
)
wait_for_vue_resource
(
spinner:
false
)
find
(
'.dropdown-menu-close'
).
click
end
end
# Test after reload
page
.
evaluate_script
'window.location.reload()'
wait_for_vue_resource
page
.
within
(
find
(
'.board'
,
match: :first
))
do
expect
(
page
.
find
(
'.board-header'
)).
to
have_content
(
'1'
)
expect
(
page
).
to
have_selector
(
'.card'
,
count:
1
)
end
page
.
within
(
find
(
'.board:nth-child(2)'
))
do
expect
(
page
.
find
(
'.board-header'
)).
to
have_content
(
'0'
)
expect
(
page
).
to
have_selector
(
'.card'
,
count:
0
)
end
end
it
'infinite scrolls list with label filter'
do
50
.
times
do
create
(
:labeled_issue
,
project:
project
,
labels:
[
testing
])
...
...
spec/features/dashboard/snippets_spec.rb
0 → 100644
View file @
170e9d24
require
'spec_helper'
describe
'Dashboard snippets'
,
feature:
true
do
context
'when the project has snippets'
do
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let!
(
:snippets
)
{
create_list
(
:project_snippet
,
2
,
:public
,
author:
project
.
owner
,
project:
project
)
}
before
do
allow
(
Snippet
).
to
receive
(
:default_per_page
).
and_return
(
1
)
login_as
(
project
.
owner
)
visit
dashboard_snippets_path
end
it_behaves_like
'paginated snippets'
end
end
spec/features/issues_spec.rb
View file @
170e9d24
...
...
@@ -369,6 +369,24 @@ describe 'Issues', feature: true do
end
end
describe
'update labels from issue#show'
,
js:
true
do
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
author:
@user
,
assignee:
@user
)
}
let!
(
:label
)
{
create
(
:label
,
project:
project
)
}
before
do
visit
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
)
end
it
'will not send ajax request when no data is changed'
do
page
.
within
'.labels'
do
click_link
'Edit'
first
(
'.dropdown-menu-close'
).
click
expect
(
page
).
not_to
have_selector
(
'.block-loading'
)
end
end
end
describe
'update assignee from issue#show'
do
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
author:
@user
,
assignee:
@user
)
}
...
...
spec/features/projects/snippets_spec.rb
0 → 100644
View file @
170e9d24
require
'spec_helper'
describe
'Project snippets'
,
feature:
true
do
context
'when the project has snippets'
do
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let!
(
:snippets
)
{
create_list
(
:project_snippet
,
2
,
:public
,
author:
project
.
owner
,
project:
project
)
}
before
do
allow
(
Snippet
).
to
receive
(
:default_per_page
).
and_return
(
1
)
visit
namespace_project_snippets_path
(
project
.
namespace
,
project
)
end
it_behaves_like
'paginated snippets'
end
end
spec/features/snippets_spec.rb
0 → 100644
View file @
170e9d24
require
'spec_helper'
describe
'Snippets'
,
feature:
true
do
context
'when the project has snippets'
do
let
(
:project
)
{
create
(
:empty_project
,
:public
)
}
let!
(
:snippets
)
{
create_list
(
:project_snippet
,
2
,
:public
,
author:
project
.
owner
,
project:
project
)
}
before
do
allow
(
Snippet
).
to
receive
(
:default_per_page
).
and_return
(
1
)
visit
snippets_path
(
username:
project
.
owner
.
username
)
end
it_behaves_like
'paginated snippets'
end
end
spec/features/unsubscribe_links_spec.rb
View file @
170e9d24
...
...
@@ -11,7 +11,7 @@ describe 'Unsubscribe links', feature: true do
let
(
:mail
)
{
ActionMailer
::
Base
.
deliveries
.
last
}
let
(
:body
)
{
Capybara
::
Node
::
Simple
.
new
(
mail
.
default_part_body
.
to_s
)
}
let
(
:header_link
)
{
mail
.
header
[
'List-Unsubscribe'
]
}
let
(
:header_link
)
{
mail
.
header
[
'List-Unsubscribe'
]
.
to_s
[
1
..-
2
]
}
# Strip angle brackets
let
(
:body_link
)
{
body
.
find_link
(
'unsubscribe'
)[
'href'
]
}
before
do
...
...
spec/features/users/snippets_spec.rb
View file @
170e9d24
...
...
@@ -3,30 +3,16 @@ require 'spec_helper'
describe
'Snippets tab on a user profile'
,
feature:
true
,
js:
true
do
include
WaitForAjax
let
(
:user
)
{
create
(
:user
)
}
context
'when the user has snippets'
do
let
(
:user
)
{
create
(
:user
)
}
let!
(
:snippets
)
{
create_list
(
:snippet
,
2
,
:public
,
author:
user
)
}
before
do
create_list
(
:snippet
,
25
,
:public
,
author:
user
)
allow
(
Snippet
).
to
receive
(
:default_per_page
).
and_return
(
1
)
visit
user_path
(
user
)
page
.
within
(
'.user-profile-nav'
)
{
click_link
'Snippets'
}
wait_for_ajax
end
it
'is limited to 20 items per page'
do
expect
(
page
.
all
(
'.snippets-list-holder .snippet-row'
).
count
).
to
eq
(
20
)
end
context
'clicking on the link to the second page'
do
before
do
click_link
(
'2'
)
wait_for_ajax
end
it
'shows the remaining snippets'
do
expect
(
page
.
all
(
'.snippets-list-holder .snippet-row'
).
count
).
to
eq
(
5
)
end
end
it_behaves_like
'paginated snippets'
,
remote:
true
end
end
spec/helpers/projects_helper_spec.rb
View file @
170e9d24
...
...
@@ -11,7 +11,7 @@ describe ProjectsHelper do
describe
"can_change_visibility_level?"
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
create
(
:
user
)
}
let
(
:user
)
{
create
(
:
project_member
,
:reporter
,
user:
create
(
:user
),
project:
project
).
user
}
let
(
:fork_project
)
{
Projects
::
ForkService
.
new
(
project
,
user
).
execute
}
it
"returns false if there are no appropriate permissions"
do
...
...
spec/javascripts/labels_issue_sidebar_spec.js.es6
View file @
170e9d24
...
...
@@ -48,9 +48,9 @@
setTimeout(() => {
expect($('.dropdown-content a').length).toBe(10);
$('.dropdow
-content a').each((i, $link) =>
{
if (i <
5
) {
$
link
.get(0).click();
$('.dropdow
n-content a').each(function (i)
{
if (i <
saveLabelCount
) {
$
(this)
.get(0).click();
}
});
...
...
@@ -70,9 +70,9 @@
setTimeout(() => {
expect($('.dropdown-content a').length).toBe(10);
$('.dropdow
-content a').each((i, $link) =>
{
if (i <
5
) {
$
link
.get(0).click();
$('.dropdow
n-content a').each(function (i)
{
if (i <
saveLabelCount
) {
$
(this)
.get(0).click();
}
});
...
...
@@ -86,4 +86,3 @@
});
});
})();
spec/lib/gitlab/auth_spec.rb
View file @
170e9d24
...
...
@@ -64,7 +64,7 @@ describe Gitlab::Auth, lib: true do
it
'recognizes user lfs tokens'
do
user
=
create
(
:user
)
ip
=
'ip'
token
=
Gitlab
::
LfsToken
.
new
(
user
).
generate
token
=
Gitlab
::
LfsToken
.
new
(
user
).
token
expect
(
gl_auth
).
to
receive
(
:rate_limit!
).
with
(
ip
,
success:
true
,
login:
user
.
username
)
expect
(
gl_auth
.
find_for_git_client
(
user
.
username
,
token
,
project:
nil
,
ip:
ip
)).
to
eq
(
Gitlab
::
Auth
::
Result
.
new
(
user
,
nil
,
:lfs_token
,
full_authentication_abilities
))
...
...
@@ -73,7 +73,7 @@ describe Gitlab::Auth, lib: true do
it
'recognizes deploy key lfs tokens'
do
key
=
create
(
:deploy_key
)
ip
=
'ip'
token
=
Gitlab
::
LfsToken
.
new
(
key
).
generate
token
=
Gitlab
::
LfsToken
.
new
(
key
).
token
expect
(
gl_auth
).
to
receive
(
:rate_limit!
).
with
(
ip
,
success:
true
,
login:
"lfs+deploy-key-
#{
key
.
id
}
"
)
expect
(
gl_auth
.
find_for_git_client
(
"lfs+deploy-key-
#{
key
.
id
}
"
,
token
,
project:
nil
,
ip:
ip
)).
to
eq
(
Gitlab
::
Auth
::
Result
.
new
(
key
,
nil
,
:lfs_deploy_token
,
read_authentication_abilities
))
...
...
spec/lib/gitlab/elastic/search_results_spec.rb
View file @
170e9d24
...
...
@@ -374,7 +374,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do
Gitlab
::
Elastic
::
Helper
.
refresh_index
end
it
'f
ou
nds blobs'
do
it
'f
i
nds blobs'
do
results
=
described_class
.
new
(
user
,
'def'
,
limit_project_ids
)
blobs
=
results
.
objects
(
'blobs'
)
...
...
@@ -382,7 +382,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do
expect
(
results
.
blobs_count
).
to
eq
4
end
it
'f
ou
nds blobs from public projects only'
do
it
'f
i
nds blobs from public projects only'
do
project_2
=
create
:project
,
:private
project_2
.
repository
.
index_blobs
Gitlab
::
Elastic
::
Helper
.
refresh_index
...
...
@@ -408,7 +408,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do
Gitlab
::
Elastic
::
Helper
.
refresh_index
end
it
'f
ou
nds commits'
do
it
'f
i
nds commits'
do
results
=
described_class
.
new
(
user
,
'add'
,
limit_project_ids
)
commits
=
results
.
objects
(
'commits'
)
...
...
@@ -416,7 +416,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do
expect
(
results
.
commits_count
).
to
eq
5
end
it
'f
ou
nds commits from public projects only'
do
it
'f
i
nds commits from public projects only'
do
project_2
=
create
:project
,
:private
project_2
.
repository
.
index_commits
Gitlab
::
Elastic
::
Helper
.
refresh_index
...
...
@@ -434,4 +434,190 @@ describe Gitlab::Elastic::SearchResults, lib: true do
expect
(
results
.
commits_count
).
to
eq
0
end
end
describe
'Visibility levels'
do
let
(
:internal_project
)
{
create
(
:project
,
:internal
,
description:
"Internal project"
)
}
let
(
:private_project1
)
{
create
(
:project
,
:private
,
description:
"Private project"
)
}
let
(
:private_project2
)
{
create
(
:project
,
:private
,
description:
"Private project where I'm a member"
)
}
let
(
:public_project
)
{
create
(
:project
,
:public
,
description:
"Public project"
)
}
let
(
:limit_project_ids
)
{
[
private_project2
.
id
]
}
before
do
private_project2
.
project_members
.
create
(
user:
user
,
access_level:
ProjectMember
::
DEVELOPER
)
end
context
'Issues'
do
it
'finds right set of issues'
do
issue_1
=
create
:issue
,
project:
internal_project
,
title:
"Internal project"
create
:issue
,
project:
private_project1
,
title:
"Private project"
issue_3
=
create
:issue
,
project:
private_project2
,
title:
"Private project where I'm a member"
issue_4
=
create
:issue
,
project:
public_project
,
title:
"Public project"
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'project'
,
limit_project_ids
)
issues
=
results
.
objects
(
'issues'
)
expect
(
issues
).
to
include
issue_1
expect
(
issues
).
to
include
issue_3
expect
(
issues
).
to
include
issue_4
expect
(
results
.
issues_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'project'
,
[])
issues
=
results
.
objects
(
'issues'
)
expect
(
issues
).
to
include
issue_4
expect
(
results
.
issues_count
).
to
eq
1
end
end
context
'Milestones'
do
it
'finds right set of milestine'
do
milestone_1
=
create
:milestone
,
project:
internal_project
,
title:
"Internal project"
create
:milestone
,
project:
private_project1
,
title:
"Private project"
milestone_3
=
create
:milestone
,
project:
private_project2
,
title:
"Private project where I'm a member"
milestone_4
=
create
:milestone
,
project:
public_project
,
title:
"Public project"
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'project'
,
limit_project_ids
)
milestones
=
results
.
objects
(
'milestones'
)
expect
(
milestones
).
to
include
milestone_1
expect
(
milestones
).
to
include
milestone_3
expect
(
milestones
).
to
include
milestone_4
expect
(
results
.
milestones_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'project'
,
[])
milestones
=
results
.
objects
(
'milestones'
)
expect
(
milestones
).
to
include
milestone_4
expect
(
results
.
milestones_count
).
to
eq
1
end
end
context
'Projects'
do
it
'finds right set of projects'
do
internal_project
private_project1
private_project2
public_project
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'project'
,
limit_project_ids
)
milestones
=
results
.
objects
(
'projects'
)
expect
(
milestones
).
to
include
internal_project
expect
(
milestones
).
to
include
private_project2
expect
(
milestones
).
to
include
public_project
expect
(
results
.
projects_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'project'
,
[])
projects
=
results
.
objects
(
'projects'
)
expect
(
projects
).
to
include
public_project
expect
(
results
.
projects_count
).
to
eq
1
end
end
context
'Merge Requests'
do
it
'finds right set of merge requests'
do
merge_request_1
=
create
:merge_request
,
target_project:
internal_project
,
source_project:
internal_project
,
title:
"Internal project"
create
:merge_request
,
target_project:
private_project1
,
source_project:
private_project1
,
title:
"Private project"
merge_request_3
=
create
:merge_request
,
target_project:
private_project2
,
source_project:
private_project2
,
title:
"Private project where I'm a member"
merge_request_4
=
create
:merge_request
,
target_project:
public_project
,
source_project:
public_project
,
title:
"Public project"
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'project'
,
limit_project_ids
)
merge_requests
=
results
.
objects
(
'merge_requests'
)
expect
(
merge_requests
).
to
include
merge_request_1
expect
(
merge_requests
).
to
include
merge_request_3
expect
(
merge_requests
).
to
include
merge_request_4
expect
(
results
.
merge_requests_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'project'
,
[])
merge_requests
=
results
.
objects
(
'merge_requests'
)
expect
(
merge_requests
).
to
include
merge_request_4
expect
(
results
.
merge_requests_count
).
to
eq
1
end
end
context
'Commits'
do
it
'finds right set of commits'
do
[
internal_project
,
private_project1
,
private_project2
,
public_project
].
each
do
|
project
|
project
.
repository
.
commit_file
(
user
,
'test-file'
,
'search test'
,
'search test'
,
'master'
,
false
)
project
.
repository
.
index_commits
end
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'search'
,
limit_project_ids
)
commits
=
results
.
objects
(
'commits'
)
expect
(
commits
.
map
(
&
:project
)).
to
match_array
[
internal_project
,
private_project2
,
public_project
]
expect
(
results
.
commits_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'search'
,
[])
commits
=
results
.
objects
(
'commits'
)
expect
(
commits
.
first
.
project
).
to
eq
public_project
expect
(
results
.
commits_count
).
to
eq
1
end
end
context
'Blobs'
do
it
'finds right set of blobs'
do
[
internal_project
,
private_project1
,
private_project2
,
public_project
].
each
do
|
project
|
project
.
repository
.
commit_file
(
user
,
'test-file'
,
'tesla'
,
'search test'
,
'master'
,
false
)
project
.
repository
.
index_blobs
end
Gitlab
::
Elastic
::
Helper
.
refresh_index
# Authenticated search
results
=
described_class
.
new
(
user
,
'tesla'
,
limit_project_ids
)
blobs
=
results
.
objects
(
'blobs'
)
expect
(
blobs
.
map
{
|
blob
|
blob
.
_parent
.
to_i
}).
to
match_array
[
internal_project
.
id
,
private_project2
.
id
,
public_project
.
id
]
expect
(
results
.
blobs_count
).
to
eq
3
# Unauthenticated search
results
=
described_class
.
new
(
nil
,
'tesla'
,
[])
blobs
=
results
.
objects
(
'blobs'
)
expect
(
blobs
.
first
.
_parent
.
to_i
).
to
eq
public_project
.
id
.
to_i
expect
(
results
.
blobs_count
).
to
eq
1
end
end
end
end
spec/lib/gitlab/import_export/project.json
View file @
170e9d24
...
...
@@ -2231,6 +2231,31 @@
],
"milestones"
:
[
{
"id"
:
1
,
"title"
:
"test milestone"
,
"project_id"
:
8
,
"description"
:
"test milestone"
,
"due_date"
:
null
,
"created_at"
:
"2016-06-14T15:02:04.415Z"
,
"updated_at"
:
"2016-06-14T15:02:04.415Z"
,
"state"
:
"active"
,
"iid"
:
1
,
"events"
:
[
{
"id"
:
487
,
"target_type"
:
"Milestone"
,
"target_id"
:
1
,
"title"
:
null
,
"data"
:
null
,
"project_id"
:
46
,
"created_at"
:
"2016-06-14T15:02:04.418Z"
,
"updated_at"
:
"2016-06-14T15:02:04.418Z"
,
"action"
:
1
,
"author_id"
:
18
}
]
},
{
"id"
:
20
,
"title"
:
"v4.0"
,
...
...
@@ -7373,5 +7398,16 @@
}
]
}
]
],
"project_feature"
:
{
"builds_access_level"
:
0
,
"created_at"
:
"2014-12-26T09:26:45.000Z"
,
"id"
:
2
,
"issues_access_level"
:
0
,
"merge_requests_access_level"
:
20
,
"project_id"
:
4
,
"snippets_access_level"
:
20
,
"updated_at"
:
"2016-09-23T11:58:28.000Z"
,
"wiki_access_level"
:
20
}
}
\ No newline at end of file
spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
View file @
170e9d24
...
...
@@ -107,6 +107,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do
expect
(
Label
.
first
.
label_links
.
first
.
target
).
not_to
be_nil
end
it
'has a project feature'
do
restored_project_json
expect
(
project
.
project_feature
).
not_to
be_nil
end
it
'restores the correct service'
do
restored_project_json
...
...
spec/lib/gitlab/lfs_token_spec.rb
View file @
170e9d24
require
'spec_helper'
describe
Gitlab
::
LfsToken
,
lib:
true
do
describe
'#
generate and #value
'
do
describe
'#
token
'
do
shared_examples
'an LFS token generator'
do
it
'returns a randomly generated token'
do
token
=
handler
.
generate
token
=
handler
.
token
expect
(
token
).
not_to
be_nil
expect
(
token
).
to
be_a
String
...
...
@@ -12,9 +12,9 @@ describe Gitlab::LfsToken, lib: true do
end
it
'returns the correct token based on the key'
do
token
=
handler
.
generate
token
=
handler
.
token
expect
(
handler
.
value
).
to
eq
(
token
)
expect
(
handler
.
token
).
to
eq
(
token
)
end
end
...
...
spec/mailers/shared/notify.rb
View file @
170e9d24
...
...
@@ -169,8 +169,9 @@ shared_examples 'it should show Gmail Actions View Commit link' do
end
shared_examples
'an unsubscribeable thread'
do
it
'has a List-Unsubscribe header'
do
it
'has a List-Unsubscribe header
in the correct format
'
do
is_expected
.
to
have_header
'List-Unsubscribe'
,
/unsubscribe/
is_expected
.
to
have_header
'List-Unsubscribe'
,
/^<.+>$/
end
it
{
is_expected
.
to
have_body_text
/unsubscribe/
}
...
...
spec/models/concerns/elastic/project_spec.rb
View file @
170e9d24
...
...
@@ -24,9 +24,9 @@ describe Project, elastic: true do
Gitlab
::
Elastic
::
Helper
.
refresh_index
end
expect
(
described_class
.
elastic_search
(
'test'
,
options:
{
pids:
project_ids
}).
total_count
).
to
eq
(
1
)
expect
(
described_class
.
elastic_search
(
'test1'
,
options:
{
pids:
project_ids
}).
total_count
).
to
eq
(
1
)
expect
(
described_class
.
elastic_search
(
'someone_elses_project'
,
options:
{
pids:
project_ids
}).
total_count
).
to
eq
(
0
)
expect
(
described_class
.
elastic_search
(
'test'
,
options:
{
p
roject_
ids:
project_ids
}).
total_count
).
to
eq
(
1
)
expect
(
described_class
.
elastic_search
(
'test1'
,
options:
{
p
roject_
ids:
project_ids
}).
total_count
).
to
eq
(
1
)
expect
(
described_class
.
elastic_search
(
'someone_elses_project'
,
options:
{
p
roject_
ids:
project_ids
}).
total_count
).
to
eq
(
0
)
end
it
"finds partial matches in project names"
do
...
...
@@ -40,7 +40,7 @@ describe Project, elastic: true do
Gitlab
::
Elastic
::
Helper
.
refresh_index
end
expect
(
described_class
.
elastic_search
(
'tesla'
,
options:
{
pids:
project_ids
}).
total_count
).
to
eq
(
2
)
expect
(
described_class
.
elastic_search
(
'tesla'
,
options:
{
p
roject_
ids:
project_ids
}).
total_count
).
to
eq
(
2
)
end
it
"returns json with all needed elements"
do
...
...
spec/models/cycle_analytics/summary_spec.rb
View file @
170e9d24
...
...
@@ -34,6 +34,12 @@ describe CycleAnalytics::Summary, models: true do
expect
(
subject
.
commits
).
to
eq
(
0
)
end
it
"finds a large (> 100) snumber of commits if present"
do
Timecop
.
freeze
(
5
.
days
.
from_now
)
{
create_commit
(
"Test message"
,
project
,
user
,
'master'
,
count:
100
)
}
expect
(
subject
.
commits
).
to
eq
(
100
)
end
end
describe
"#deploys"
do
...
...
spec/models/forked_project_link_spec.rb
View file @
170e9d24
...
...
@@ -6,6 +6,7 @@ describe ForkedProjectLink, "add link on fork" do
let
(
:user
)
{
create
(
:user
,
namespace:
namespace
)
}
before
do
create
(
:project_member
,
:reporter
,
user:
user
,
project:
project_from
)
@project_to
=
fork_project
(
project_from
,
user
)
end
...
...
spec/requests/api/api_helpers_spec.rb
View file @
170e9d24
...
...
@@ -10,7 +10,8 @@ describe API::Helpers, api: true do
let
(
:key
)
{
create
(
:key
,
user:
user
)
}
let
(
:params
)
{
{}
}
let
(
:env
)
{
{}
}
let
(
:env
)
{
{
'REQUEST_METHOD'
=>
'GET'
}
}
let
(
:request
)
{
Rack
::
Request
.
new
(
env
)
}
def
set_env
(
token_usr
,
identifier
)
clear_env
...
...
@@ -52,17 +53,43 @@ describe API::Helpers, api: true do
describe
".current_user"
do
subject
{
current_user
}
describe
"
when authenticating via Warde
n"
do
describe
"
Warden authenticatio
n"
do
before
{
doorkeeper_guard_returns
false
}
context
"fails"
do
it
{
is_expected
.
to
be_nil
}
context
"with invalid credentials"
do
context
"GET request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'GET'
}
it
{
is_expected
.
to
be_nil
}
end
end
context
"
succeed
s"
do
context
"
with valid credential
s"
do
before
{
warden_authenticate_returns
user
}
it
{
is_expected
.
to
eq
(
user
)
}
context
"GET request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'GET'
}
it
{
is_expected
.
to
eq
(
user
)
}
end
context
"HEAD request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'HEAD'
}
it
{
is_expected
.
to
eq
(
user
)
}
end
context
"PUT request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'PUT'
}
it
{
is_expected
.
to
be_nil
}
end
context
"POST request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'POST'
}
it
{
is_expected
.
to
be_nil
}
end
context
"DELETE request"
do
before
{
env
[
'REQUEST_METHOD'
]
=
'DELETE'
}
it
{
is_expected
.
to
be_nil
}
end
end
end
...
...
spec/requests/api/fork_spec.rb
View file @
170e9d24
...
...
@@ -18,7 +18,7 @@ describe API::API, api: true do
end
let
(
:project_user2
)
do
create
(
:project_member
,
:
guest
,
user:
user2
,
project:
project
)
create
(
:project_member
,
:
reporter
,
user:
user2
,
project:
project
)
end
describe
'POST /projects/fork/:id'
do
...
...
spec/requests/api/internal_spec.rb
View file @
170e9d24
...
...
@@ -111,7 +111,7 @@ describe API::API, api: true do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'username'
]).
to
eq
(
user
.
username
)
expect
(
json_response
[
'lfs_token'
]).
to
eq
(
Gitlab
::
LfsToken
.
new
(
key
).
value
)
expect
(
json_response
[
'lfs_token'
]).
to
eq
(
Gitlab
::
LfsToken
.
new
(
key
).
token
)
expect
(
json_response
[
'repository_http_path'
]).
to
eq
(
project
.
http_url_to_repo
)
end
...
...
@@ -131,7 +131,7 @@ describe API::API, api: true do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'username'
]).
to
eq
(
"lfs+deploy-key-
#{
key
.
id
}
"
)
expect
(
json_response
[
'lfs_token'
]).
to
eq
(
Gitlab
::
LfsToken
.
new
(
key
).
value
)
expect
(
json_response
[
'lfs_token'
]).
to
eq
(
Gitlab
::
LfsToken
.
new
(
key
).
token
)
expect
(
json_response
[
'repository_http_path'
]).
to
eq
(
project
.
http_url_to_repo
)
end
end
...
...
spec/requests/jwt_controller_spec.rb
View file @
170e9d24
...
...
@@ -39,7 +39,7 @@ describe JwtController do
subject!
{
get
'/jwt/auth'
,
parameters
,
headers
}
it
{
expect
(
response
).
to
have_http_status
(
40
3
)
}
it
{
expect
(
response
).
to
have_http_status
(
40
1
)
}
end
end
...
...
@@ -77,7 +77,7 @@ describe JwtController do
subject!
{
get
'/jwt/auth'
,
parameters
,
headers
}
it
{
expect
(
response
).
to
have_http_status
(
40
3
)
}
it
{
expect
(
response
).
to
have_http_status
(
40
1
)
}
end
end
...
...
spec/requests/lfs_http_spec.rb
View file @
170e9d24
...
...
@@ -257,6 +257,29 @@ describe 'Git LFS API and storage' do
it_behaves_like
'responds with a file'
end
describe
'when using a user key'
do
let
(
:authorization
)
{
authorize_user_key
}
context
'when user allowed'
do
let
(
:update_permissions
)
do
project
.
team
<<
[
user
,
:master
]
project
.
lfs_objects
<<
lfs_object
end
it_behaves_like
'responds with a file'
end
context
'when user not allowed'
do
let
(
:update_permissions
)
do
project
.
lfs_objects
<<
lfs_object
end
it
'responds with status 404'
do
expect
(
response
).
to
have_http_status
(
404
)
end
end
end
context
'when build is authorized as'
do
let
(
:authorization
)
{
authorize_ci_project
}
...
...
@@ -1131,7 +1154,11 @@ describe 'Git LFS API and storage' do
end
def
authorize_deploy_key
ActionController
::
HttpAuthentication
::
Basic
.
encode_credentials
(
"lfs+deploy-key-
#{
key
.
id
}
"
,
Gitlab
::
LfsToken
.
new
(
key
).
generate
)
ActionController
::
HttpAuthentication
::
Basic
.
encode_credentials
(
"lfs+deploy-key-
#{
key
.
id
}
"
,
Gitlab
::
LfsToken
.
new
(
key
).
token
)
end
def
authorize_user_key
ActionController
::
HttpAuthentication
::
Basic
.
encode_credentials
(
user
.
username
,
Gitlab
::
LfsToken
.
new
(
user
).
token
)
end
def
fork_project
(
project
,
user
,
object
=
nil
)
...
...
spec/services/projects/fork_service_spec.rb
View file @
170e9d24
...
...
@@ -12,12 +12,26 @@ describe Projects::ForkService, services: true do
description:
'wow such project'
)
@to_namespace
=
create
(
:namespace
)
@to_user
=
create
(
:user
,
namespace:
@to_namespace
)
@from_project
.
add_user
(
@to_user
,
:developer
)
end
context
'fork project'
do
context
'when forker is a guest'
do
before
do
@guest
=
create
(
:user
)
@from_project
.
add_user
(
@guest
,
:guest
)
end
subject
{
fork_project
(
@from_project
,
@guest
)
}
it
{
is_expected
.
not_to
be_persisted
}
it
{
expect
(
subject
.
errors
[
:forked_from_project_id
]).
to
eq
([
'is forbidden'
])
}
end
describe
"successfully creates project in the user namespace"
do
let
(
:to_project
)
{
fork_project
(
@from_project
,
@to_user
)
}
it
{
expect
(
to_project
).
to
be_persisted
}
it
{
expect
(
to_project
.
errors
).
to
be_empty
}
it
{
expect
(
to_project
.
owner
).
to
eq
(
@to_user
)
}
it
{
expect
(
to_project
.
namespace
).
to
eq
(
@to_user
.
namespace
)
}
it
{
expect
(
to_project
.
star_count
).
to
be_zero
}
...
...
@@ -29,7 +43,9 @@ describe Projects::ForkService, services: true do
it
"fails due to validation, not transaction failure"
do
@existing_project
=
create
(
:project
,
creator_id:
@to_user
.
id
,
name:
@from_project
.
name
,
namespace:
@to_namespace
)
@to_project
=
fork_project
(
@from_project
,
@to_user
)
expect
(
@existing_project
.
persisted?
).
to
be_truthy
expect
(
@existing_project
).
to
be_persisted
expect
(
@to_project
).
not_to
be_persisted
expect
(
@to_project
.
errors
[
:name
]).
to
eq
([
'has already been taken'
])
expect
(
@to_project
.
errors
[
:path
]).
to
eq
([
'has already been taken'
])
end
...
...
@@ -81,18 +97,23 @@ describe Projects::ForkService, services: true do
@group
=
create
(
:group
)
@group
.
add_user
(
@group_owner
,
GroupMember
::
OWNER
)
@group
.
add_user
(
@developer
,
GroupMember
::
DEVELOPER
)
@project
.
add_user
(
@developer
,
:developer
)
@project
.
add_user
(
@group_owner
,
:developer
)
@opts
=
{
namespace:
@group
}
end
context
'fork project for group'
do
it
'group owner successfully forks project into the group'
do
to_project
=
fork_project
(
@project
,
@group_owner
,
@opts
)
expect
(
to_project
).
to
be_persisted
expect
(
to_project
.
errors
).
to
be_empty
expect
(
to_project
.
owner
).
to
eq
(
@group
)
expect
(
to_project
.
namespace
).
to
eq
(
@group
)
expect
(
to_project
.
name
).
to
eq
(
@project
.
name
)
expect
(
to_project
.
path
).
to
eq
(
@project
.
path
)
expect
(
to_project
.
description
).
to
eq
(
@project
.
description
)
expect
(
to_project
.
star_count
).
to
be_zero
expect
(
to_project
.
star_count
).
to
be_zero
end
end
...
...
spec/services/system_note_service_spec.rb
View file @
170e9d24
...
...
@@ -445,7 +445,7 @@ describe SystemNoteService, services: true do
end
context
'commit with cross-reference from fork'
do
let
(
:author2
)
{
create
(
:
user
)
}
let
(
:author2
)
{
create
(
:
project_member
,
:reporter
,
user:
create
(
:user
),
project:
project
).
user
}
let
(
:forked_project
)
do
fp
=
Projects
::
ForkService
.
new
(
project
,
author2
).
execute
# The call to project.repository.after_import in RepositoryForkWorker does
...
...
spec/support/cycle_analytics_helpers.rb
View file @
170e9d24
...
...
@@ -4,24 +4,28 @@ module CycleAnalyticsHelpers
create_commit
(
"Commit for #
#{
issue
.
iid
}
"
,
issue
.
project
,
user
,
branch_name
)
end
def
create_commit
(
message
,
project
,
user
,
branch_name
)
filename
=
random_git_name
def
create_commit
(
message
,
project
,
user
,
branch_name
,
count:
1
)
oldrev
=
project
.
repository
.
commit
(
branch_name
).
sha
commit_shas
=
Array
.
new
(
count
)
do
|
index
|
filename
=
random_git_name
options
=
{
committer:
project
.
repository
.
user_to_committer
(
user
),
author:
project
.
repository
.
user_to_committer
(
user
),
commit:
{
message:
message
,
branch:
branch_name
,
update_ref:
true
},
file:
{
content:
"content"
,
path:
filename
,
update:
false
}
}
options
=
{
committer:
project
.
repository
.
user_to_committer
(
user
),
author:
project
.
repository
.
user_to_committer
(
user
),
commit:
{
message:
message
,
branch:
branch_name
,
update_ref:
true
},
file:
{
content:
"content"
,
path:
filename
,
update:
false
}
}
commit_sha
=
Gitlab
::
Git
::
Blob
.
commit
(
project
.
repository
,
options
)
project
.
repository
.
commit
(
commit_sha
)
commit_sha
=
Gitlab
::
Git
::
Blob
.
commit
(
project
.
repository
,
options
)
project
.
repository
.
commit
(
commit_sha
)
commit_sha
end
GitPushService
.
new
(
project
,
user
,
oldrev:
oldrev
,
newrev:
commit_sha
,
newrev:
commit_sha
s
.
last
,
ref:
'refs/heads/master'
).
execute
end
...
...
spec/support/snippets_shared_examples.rb
0 → 100644
View file @
170e9d24
# These shared examples expect a `snippets` array of snippets
RSpec
.
shared_examples
'paginated snippets'
do
|
remote:
false
|
it
"is limited to
#{
Snippet
.
default_per_page
}
items per page"
do
expect
(
page
.
all
(
'.snippets-list-holder .snippet-row'
).
count
).
to
eq
(
Snippet
.
default_per_page
)
end
context
'clicking on the link to the second page'
do
before
do
click_link
(
'2'
)
wait_for_ajax
if
remote
end
it
'shows the remaining snippets'
do
remaining_snippets_count
=
[
snippets
.
size
-
Snippet
.
default_per_page
,
Snippet
.
default_per_page
].
min
expect
(
page
).
to
have_selector
(
'.snippets-list-holder .snippet-row'
,
count:
remaining_snippets_count
)
end
end
end
spec/views/ci/lints/show.html.haml_spec.rb
0 → 100644
View file @
170e9d24
require
'spec_helper'
describe
'ci/lints/show'
do
include
Devise
::
TestHelpers
before
do
assign
(
:status
,
true
)
assign
(
:stages
,
%w[test]
)
assign
(
:builds
,
builds
)
end
context
'when builds attrbiutes contain HTML nodes'
do
let
(
:builds
)
do
[
{
name:
'rspec'
,
stage:
'test'
,
commands:
'<h1>rspec</h1>'
}
]
end
it
'does not render HTML elements'
do
render
expect
(
rendered
).
not_to
have_css
(
'h1'
,
text:
'rspec'
)
end
end
context
'when builds attributes do not contain HTML nodes'
do
let
(
:builds
)
do
[
{
name:
'rspec'
,
stage:
'test'
,
commands:
'rspec'
}
]
end
it
'shows configuration in the table'
do
render
expect
(
rendered
).
to
have_css
(
'td pre'
,
text:
'rspec'
)
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