Commit 3832718d authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 180cd023
......@@ -26,7 +26,7 @@ gem 'marginalia', '~> 1.8.0'
# Authentication libraries
gem 'devise', '~> 4.6'
gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper', '~> 4.4.3'
gem 'doorkeeper-openid_connect', '~> 1.5'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
......
......@@ -231,7 +231,7 @@ GEM
docile (1.3.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2)
doorkeeper (4.4.3)
railties (>= 4.2)
doorkeeper-openid_connect (1.5.0)
doorkeeper (~> 4.3)
......@@ -1180,7 +1180,7 @@ DEPENDENCIES
diff_match_patch (~> 0.1.0)
diffy (~> 3.1.0)
discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3)
doorkeeper (~> 4.4.3)
doorkeeper-openid_connect (~> 1.5)
ed25519 (~> 1.2)
elasticsearch-api (~> 6.8)
......
......@@ -4,15 +4,12 @@ import SelfMonitorForm from './components/self_monitor_form.vue';
export default () => {
const el = document.querySelector('.js-self-monitoring-settings');
let selfMonitorProjectCreated;
if (el) {
selfMonitorProjectCreated = el.dataset.selfMonitoringProjectExists;
// eslint-disable-next-line no-new
new Vue({
el,
store: store({
projectEnabled: selfMonitorProjectCreated,
...el.dataset,
}),
render(createElement) {
......
......@@ -52,7 +52,7 @@ export const requestCreateProjectStatus = ({ dispatch, state }, jobId) => {
});
};
export const requestCreateProjectSuccess = ({ commit }, selfMonitorData) => {
export const requestCreateProjectSuccess = ({ commit, dispatch }, selfMonitorData) => {
commit(types.SET_LOADING, false);
commit(types.SET_PROJECT_URL, selfMonitorData.project_full_path);
commit(types.SET_ALERT_CONTENT, {
......@@ -62,6 +62,7 @@ export const requestCreateProjectSuccess = ({ commit }, selfMonitorData) => {
});
commit(types.SET_SHOW_ALERT, true);
commit(types.SET_PROJECT_CREATED, true);
dispatch('setSelfMonitor', true);
};
export const requestCreateProjectError = ({ commit }, error) => {
......
import { parseBoolean } from '~/lib/utils/common_utils';
export default (initialState = {}) => ({
projectEnabled: parseBoolean(initialState.projectEnabled) || false,
projectCreated: parseBoolean(initialState.selfMonitorProjectCreated) || false,
projectEnabled: parseBoolean(initialState.selfMonitoringProjectExists) || false,
projectCreated: parseBoolean(initialState.selfMonitoringProjectExists) || false,
createProjectEndpoint: initialState.createSelfMonitoringProjectPath || '',
deleteProjectEndpoint: initialState.deleteSelfMonitoringProjectPath || '',
createProjectStatusEndpoint: initialState.statusCreateSelfMonitoringProjectPath || '',
......
......@@ -55,6 +55,8 @@ class Admin::ApplicationsController < Admin::ApplicationController
# Only allow a trusted parameter "white list" through.
def application_params
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :trusted, :scopes)
params
.require(:doorkeeper_application)
.permit(:name, :redirect_uri, :trusted, :scopes, :confidential)
end
end
......@@ -7,13 +7,13 @@ module Groups
before_action :feature_flag_group_container_registry_browser!
def index
track_event(:list_repositories)
respond_to do |format|
format.html
format.json do
@images = group.container_repositories.with_api_entity_associations
track_event(:list_repositories)
render json: ContainerRepositoriesSerializer
.new(current_user: current_user)
.represent_read_only(@images)
......
......@@ -7,12 +7,13 @@ module Projects
before_action :ensure_root_container_repository!, only: [:index]
def index
@images = project.container_repositories
track_event(:list_repositories)
respond_to do |format|
format.html
format.json do
@images = project.container_repositories
track_event(:list_repositories)
render json: ContainerRepositoriesSerializer
.new(project: project, current_user: current_user)
.represent(@images)
......
......@@ -101,6 +101,7 @@ class User < ApplicationRecord
# Groups
has_many :members
has_one :max_access_level_membership, -> { select(:id, :user_id, :access_level).order(access_level: :desc).readonly }, class_name: 'Member'
has_many :group_members, -> { where(requested_at: nil) }, source: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
......@@ -1027,7 +1028,7 @@ class User < ApplicationRecord
end
def highest_role
members.maximum(:access_level) || Gitlab::Access::NO_ACCESS
max_access_level_membership&.access_level || Gitlab::Access::NO_ACCESS
end
def accessible_deploy_keys
......
......@@ -30,6 +30,14 @@
%span.form-text.text-muted
Trusted applications are automatically authorized on GitLab OAuth flow.
= content_tag :div, class: 'form-group row' do
.col-sm-2.col-form-label.pt-0
= f.label :confidential
.col-sm-10
= f.check_box :confidential
%span.form-text.text-muted
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
.form-group.row
.col-sm-2.col-form-label.pt-0
= f.label :scopes
......
......@@ -12,6 +12,7 @@
%th Callback URL
%th Clients
%th Trusted
%th Confidential
%th
%th
%tbody.oauth-applications
......@@ -21,6 +22,7 @@
%td= application.redirect_uri
%td= @application_counts[application.id].to_i
%td= application.trusted? ? 'Y': 'N'
%td= application.confidential? ? 'Y': 'N'
%td= link_to 'Edit', edit_admin_application_path(application), class: 'btn btn-link'
%td= render 'delete_form', application: application
= paginate @applications, theme: 'gitlab'
......@@ -36,6 +36,12 @@
%td
= @application.trusted? ? 'Y' : 'N'
%tr
%td
Confidential
%td
= @application.confidential? ? 'Y' : 'N'
= render "shared/tokens/scopes_list", token: @application
.form-actions
......
......@@ -15,6 +15,12 @@
%span.form-text.text-muted
= _('Use <code>%{native_redirect_uri}</code> for local tests').html_safe % { native_redirect_uri: Doorkeeper.configuration.native_redirect_uri }
.form-group.form-check
= f.check_box :confidential, class: 'form-check-input'
= f.label :confidential, class: 'label-bold form-check-label'
%span.form-text.text-muted
= _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
.form-group
= f.label :scopes, class: 'label-bold'
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
......
......@@ -34,6 +34,12 @@
%div
%span.monospace= uri
%tr
%td
= _('Confidential')
%td
= @application.confidential? ? _('Yes') : _('No')
= render "shared/tokens/scopes_list", token: @application
.form-actions
......
---
title: Limit size of diffs returned by /projects/:id/repository/compare API endpoint
merge_request: 22658
author:
type: fixed
---
title: Fixes AutoMergeProcessWorker failing when merge train service is not available
for a merge request
merge_request: 23407
author:
type: fixed
---
title: Let tie breaker order follow primary sort direction (API)
merge_request: 22795
author:
type: changed
---
title: Expose is_using_seat attribute for Member in API
merge_request: 21496
author:
type: added
---
title: Upgrade Doorkeeper to 4.4.3 to address CVE-2018-1000211
merge_request: 20953
author:
type: security
......@@ -118,8 +118,8 @@ end
# app created does not match the complete list of scopes of the configured app.
# It also prevents the OAuth authorize application window to appear every time.
# Remove after we upgrade the doorkeeper gem from version 4.3.2
if Doorkeeper.gem_version > Gem::Version.new('4.3.2')
# Remove after we upgrade the doorkeeper gem from version 4.x
if Doorkeeper.gem_version > Gem::Version.new('5.0.0')
raise "Doorkeeper was upgraded, please remove the monkey patch in #{__FILE__}"
end
......
# frozen_string_literal: true
class AddConfidentialToDoorkeeperApplication < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
:oauth_applications,
:confidential,
:boolean,
default: false, # assume all existing applications are non-confidential
allow_null: false
)
# set the default to true so that all future applications are confidential by default
change_column_default(:oauth_applications, :confidential, true)
end
def down
remove_column :oauth_applications, :confidential
end
end
......@@ -2853,6 +2853,7 @@ ActiveRecord::Schema.define(version: 2020_01_21_132641) do
t.integer "owner_id"
t.string "owner_type"
t.boolean "trusted", default: false, null: false
t.boolean "confidential", default: true, null: false
t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end
......
......@@ -284,32 +284,3 @@ command and not the PID(s) of the started Sidekiq processes.
The Rails environment can be set by passing the `--environment` flag to the
`sidekiq-cluster` command, or by setting `RAILS_ENV` to a non-empty value. The
default value can be found in `/opt/gitlab/etc/gitlab-rails/env/RAILS_ENV`.
### Using negation
You're able to run all queues in the `all_queues.yml` file (or the equivalent EE
file) on a single or multiple processes with exceptions using the `--negate`
flag.
For example, say you want to run a single process for all queues,
except `process_commit` and `post_receive`:
```bash
/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive --negate
```
For multiple processes of all queues (except `process_commit` and `post_receive`):
```bash
/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive process_commit,post_receive --negate
```
### Limiting concurrency
By default, `sidekiq-cluster` will spin up extra Sidekiq processes that use
one thread per queue up to a maximum of 50. If you wish to change the cap, use
the `-m N` option. For example, this would cap the maximum number of threads to 1:
```bash
/opt/gitlab/embedded/service/gitlab-rails/ee/bin/sidekiq-cluster process_commit,post_receive -m 1
```
......@@ -22,11 +22,12 @@ POST /applications
Parameters:
| Attribute | Type | Required | Description |
|:---------------|:-------|:---------|:---------------------------------|
| `name` | string | yes | Name of the application. |
| `redirect_uri` | string | yes | Redirect URI of the application. |
| `scopes` | string | yes | Scopes of the application. |
| Attribute | Type | Required | Description |
|:---------------|:--------|:---------|:---------------------------------|
| `name` | string | yes | Name of the application. |
| `redirect_uri` | string | yes | Redirect URI of the application. |
| `scopes` | string | yes | Scopes of the application. |
| `confidential` | boolean | no | The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential. Defaults to `true` if not supplied |
Example request:
......@@ -42,7 +43,8 @@ Example response:
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication",
"secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34",
"callback_url": "http://redirect.uri"
"callback_url": "http://redirect.uri",
"confidential": true
}
```
......@@ -68,7 +70,8 @@ Example response:
"id":1,
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication",
"callback_url": "http://redirect.uri"
"callback_url": "http://redirect.uri",
"confidential": true
}
]
```
......
......@@ -128,7 +128,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.com/api/v4/pro
## Compare branches, tags or commits
This endpoint can be accessed without authentication if the repository is
publicly accessible.
publicly accessible. Note that diffs could have an empty diff string if [diff limits](../development/diffs.html#diff-limits) are reached.
```
GET /projects/:id/repository/compare
......
......@@ -14,6 +14,9 @@ module API
requires :name, type: String, desc: 'Application name'
requires :redirect_uri, type: String, desc: 'Application redirect URI'
requires :scopes, type: String, desc: 'Application scopes'
optional :confidential, type: Boolean, default: true,
desc: 'Application will be used where the client secret is confidential'
end
post do
application = Doorkeeper::Application.new(declared_params)
......
......@@ -1256,20 +1256,20 @@ module API
end
class Compare < Grape::Entity
expose :commit, using: Entities::Commit do |compare, options|
::Commit.decorate(compare.commits, nil).last
expose :commit, using: Entities::Commit do |compare, _|
compare.commits.last
end
expose :commits, using: Entities::Commit do |compare, options|
::Commit.decorate(compare.commits, nil)
expose :commits, using: Entities::Commit do |compare, _|
compare.commits
end
expose :diffs, using: Entities::Diff do |compare, options|
compare.diffs(limits: false).to_a
expose :diffs, using: Entities::Diff do |compare, _|
compare.diffs.diffs.to_a
end
expose :compare_timeout do |compare, options|
compare.diffs.overflow?
expose :compare_timeout do |compare, _|
compare.diffs.diffs.overflow?
end
expose :same, as: :compare_same_ref
......@@ -1828,6 +1828,7 @@ module API
expose :uid, as: :application_id
expose :name, as: :application_name
expose :redirect_uri, as: :callback_url
expose :confidential
end
# Use with care, this exposes the secret
......
......@@ -316,7 +316,7 @@ module API
def order_options_with_tie_breaker
order_options = { params[:order_by] => params[:sort] }
order_options['id'] ||= 'desc'
order_options['id'] ||= params[:sort] || 'asc'
order_options
end
......
......@@ -46,7 +46,7 @@ module API
end
def present_members(members)
present members, with: Entities::Member, current_user: current_user
present members, with: Entities::Member, current_user: current_user, show_seat_info: params[:show_seat_info]
end
end
end
......
......@@ -26,7 +26,7 @@ module API
private
def keyset_pagination_enabled?
params[:pagination] == 'keyset' && Feature.enabled?(:api_keyset_pagination, default_enabled: true)
params[:pagination] == 'keyset'
end
end
end
......
......@@ -19,6 +19,7 @@ module API
params do
optional :query, type: String, desc: 'A query string to search for members'
optional :user_ids, type: Array[Integer], desc: 'Array of user ids to look up for membership'
optional :show_seat_info, type: Boolean, desc: 'Show seat information for members'
use :optional_filter_params_ee
use :pagination
end
......@@ -37,6 +38,7 @@ module API
params do
optional :query, type: String, desc: 'A query string to search for members'
optional :user_ids, type: Array[Integer], desc: 'Array of user ids to look up for membership'
optional :show_seat_info, type: Boolean, desc: 'Show seat information for members'
use :pagination
end
......
......@@ -103,8 +103,13 @@ module API
optional :straight, type: Boolean, desc: 'Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)', default: false
end
get ':id/repository/compare' do
compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to], straight: params[:straight])
present compare, with: Entities::Compare
compare = CompareService.new(user_project, params[:to]).execute(user_project, params[:from], straight: params[:straight])
if compare
present compare, with: Entities::Compare
else
not_found!("Ref")
end
end
desc 'Get repository contributors' do
......
......@@ -18420,6 +18420,9 @@ msgstr ""
msgid "The amount of seconds after which a request to get a secondary node status will time out."
msgstr ""
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr ""
msgid "The branch for this project has no active pipeline configuration."
msgstr ""
......
......@@ -40,7 +40,7 @@ describe Admin::ApplicationsController do
describe 'POST #create' do
it 'creates the application' do
create_params = attributes_for(:application, trusted: true)
create_params = attributes_for(:application, trusted: true, confidential: false)
expect do
post :create, params: { doorkeeper_application: create_params }
......@@ -60,16 +60,34 @@ describe Admin::ApplicationsController do
expect(response).to render_template :new
expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
end
context 'when the params are for a confidential application' do
it 'creates a confidential application' do
create_params = attributes_for(:application, confidential: true)
expect do
post :create, params: { doorkeeper_application: create_params }
end.to change { Doorkeeper::Application.count }.by(1)
application = Doorkeeper::Application.last
expect(response).to redirect_to(admin_application_path(application))
expect(application).to have_attributes(create_params.except(:uid, :owner_type))
end
end
end
describe 'PATCH #update' do
it 'updates the application' do
patch :update, params: { id: application.id, doorkeeper_application: { redirect_uri: 'http://example.com/', trusted: true } }
doorkeeper_params = { redirect_uri: 'http://example.com/', trusted: true, confidential: false }
patch :update, params: { id: application.id, doorkeeper_application: doorkeeper_params }
application.reload
expect(response).to redirect_to(admin_application_path(application))
expect(application).to have_attributes(redirect_uri: 'http://example.com/', trusted: true)
expect(application)
.to have_attributes(redirect_uri: 'http://example.com/', trusted: true, confidential: false)
end
it 'renders the application form on errors' do
......@@ -78,5 +96,16 @@ describe Admin::ApplicationsController do
expect(response).to render_template :edit
expect(assigns[:scopes]).to be_kind_of(Doorkeeper::OAuth::Scopes)
end
context 'when updating the application to be confidential' do
it 'successfully sets the application to confidential' do
doorkeeper_params = { confidential: true }
patch :update, params: { id: application.id, doorkeeper_application: doorkeeper_params }
expect(response).to redirect_to(admin_application_path(application))
expect(application).to be_confidential
end
end
end
end
......@@ -17,6 +17,8 @@ describe Groups::Registry::RepositoriesController do
context 'GET #index' do
context 'when container registry is enabled' do
it 'show index page' do
expect(Gitlab::Tracking).not_to receive(:event)
get :index, params: {
group_id: group
}
......@@ -54,7 +56,8 @@ describe Groups::Registry::RepositoriesController do
expect(Gitlab::Tracking).to receive(:event).with(anything, 'list_repositories', {})
get :index, params: {
group_id: group
group_id: group,
format: :json
}
end
end
......
......@@ -35,6 +35,8 @@ describe Projects::Registry::RepositoriesController do
end
it 'successfully renders container repositories' do
expect(Gitlab::Tracking).not_to receive(:event)
go_to_index
expect(response).to have_gitlab_http_status(:ok)
......@@ -43,7 +45,7 @@ describe Projects::Registry::RepositoriesController do
it 'tracks the event' do
expect(Gitlab::Tracking).to receive(:event).with(anything, 'list_repositories', {})
go_to_index
go_to_index(format: :json)
end
it 'creates a root container repository' do
......
......@@ -21,18 +21,21 @@ RSpec.describe 'admin manage applications' do
expect(page).to have_content('Application ID')
expect(page).to have_content('Secret')
expect(page).to have_content('Trusted Y')
expect(page).to have_content('Confidential Y')
click_on 'Edit'
expect(page).to have_content('Edit application')
fill_in :doorkeeper_application_name, with: 'test_changed'
uncheck :doorkeeper_application_trusted
uncheck :doorkeeper_application_confidential
click_on 'Submit'
expect(page).to have_content('test_changed')
expect(page).to have_content('Application ID')
expect(page).to have_content('Secret')
expect(page).to have_content('Trusted N')
expect(page).to have_content('Confidential N')
visit admin_applications_path
page.within '.oauth-applications' do
......
......@@ -20,16 +20,19 @@ describe 'User manages applications' do
expect(page).to have_content 'Application: test'
expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret'
expect(page).to have_content 'Confidential Yes'
click_on 'Edit'
expect(page).to have_content 'Edit application'
fill_in :doorkeeper_application_name, with: 'test_changed'
uncheck :doorkeeper_application_confidential
click_on 'Save application'
expect(page).to have_content 'test_changed'
expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret'
expect(page).to have_content 'Confidential No'
visit applications_profile_path
......
{
"type": "array",
"items": {
"type": "object",
"properties" : {
"id": { "type": "integer" },
"name": { "type": "string" },
"username": { "type": "string" },
"state": { "type": "string" },
"avatar_url": { "type": ["string", "null"] },
"web_url": { "type": ["string", "null"] },
"access_level": { "type": "integer" },
"expires_at": { "type": ["date", "null"] },
"is_using_seat": { "type": "boolean" }
},
"required": [
"id", "name", "username", "state",
"web_url", "access_level", "expires_at"
],
"additionalProperties": false
}
}
......@@ -11,7 +11,7 @@ describe('self monitor component', () => {
beforeEach(() => {
store = createStore({
projectEnabled: false,
selfMonitorProjectCreated: false,
selfMonitoringProjectExists: false,
createSelfMonitoringProjectPath: '/create',
deleteSelfMonitoringProjectPath: '/delete',
});
......@@ -69,7 +69,7 @@ describe('self monitor component', () => {
it('renders the form description with a link', () => {
store = createStore({
projectEnabled: true,
selfMonitorProjectCreated: true,
selfMonitoringProjectExists: true,
createSelfMonitoringProjectPath: '/create',
deleteSelfMonitoringProjectPath: '/delete',
});
......
......@@ -140,7 +140,12 @@ describe('self monitor actions', () => {
{ type: types.SET_SHOW_ALERT, payload: true },
{ type: types.SET_PROJECT_CREATED, payload: true },
],
[],
[
{
payload: true,
type: 'setSelfMonitor',
},
],
done,
);
});
......
......@@ -188,4 +188,46 @@ describe API::Helpers do
subject.track_event('my_event', category: nil)
end
end
describe '#order_options_with_tie_breaker' do
subject { Class.new.include(described_class).new.order_options_with_tie_breaker }
before do
allow_any_instance_of(described_class).to receive(:params).and_return(params)
end
context 'with non-id order given' do
context 'with ascending order' do
let(:params) { { order_by: 'name', sort: 'asc' } }
it 'adds id based ordering with same direction as primary order' do
is_expected.to eq({ 'name' => 'asc', 'id' => 'asc' })
end
end
context 'with descending order' do
let(:params) { { order_by: 'name', sort: 'desc' } }
it 'adds id based ordering with same direction as primary order' do
is_expected.to eq({ 'name' => 'desc', 'id' => 'desc' })
end
end
end
context 'with non-id order but no direction given' do
let(:params) { { order_by: 'name' } }
it 'adds ID ASC order' do
is_expected.to eq({ 'name' => nil, 'id' => 'asc' })
end
end
context 'with id order given' do
let(:params) { { order_by: 'id', sort: 'asc' } }
it 'does not add an additional order' do
is_expected.to eq({ 'id' => 'asc' })
end
end
end
end
......@@ -25,6 +25,7 @@ describe User, :do_not_mock_admin_mode do
describe 'associations' do
it { is_expected.to have_one(:namespace) }
it { is_expected.to have_one(:status) }
it { is_expected.to have_one(:max_access_level_membership) }
it { is_expected.to have_many(:snippets).dependent(:destroy) }
it { is_expected.to have_many(:members) }
it { is_expected.to have_many(:project_members) }
......@@ -839,9 +840,36 @@ describe User, :do_not_mock_admin_mode do
describe '#highest_role' do
let(:user) { create(:user) }
let(:group) { create(:group) }
context 'with association :max_access_level_membership' do
let(:another_user) { create(:user) }
before do
create(:project, group: group) do |project|
group.add_user(user, GroupMember::GUEST)
group.add_user(another_user, GroupMember::DEVELOPER)
end
create(:project, group: create(:group)) do |project|
project.add_guest(another_user)
end
create(:project, group: create(:group)) do |project|
project.add_maintainer(user)
end
end
it 'returns the correct highest role' do
users = User.includes(:max_access_level_membership).where(id: [user.id, another_user.id])
expect(users.collect { |u| [u.id, u.highest_role] }).to contain_exactly(
[user.id, Gitlab::Access::MAINTAINER],
[another_user.id, Gitlab::Access::DEVELOPER]
)
end
end
it 'returns NO_ACCESS if none has been set' do
expect(user.highest_role).to eq(Gitlab::Access::NO_ACCESS)
end
......
......@@ -21,6 +21,7 @@ describe API::Applications, :api do
expect(json_response['application_id']).to eq application.uid
expect(json_response['secret']).to eq application.secret
expect(json_response['callback_url']).to eq application.redirect_uri
expect(json_response['confidential']).to eq application.confidential
end
it 'does not allow creating an application with the wrong redirect_uri format' do
......@@ -72,6 +73,16 @@ describe API::Applications, :api do
expect(json_response).to be_a Hash
expect(json_response['error']).to eq('scopes is missing')
end
it 'does not allow creating an application with confidential set to nil' do
expect do
post api('/applications', admin_user), params: { name: 'application_name', redirect_uri: 'http://application.url', scopes: '', confidential: nil }
end.not_to change { Doorkeeper::Application.count }
expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['message']['confidential'].first).to eq('is not included in the list')
end
end
context 'authorized user without authorization' do
......
......@@ -362,6 +362,29 @@ describe API::Repositories do
expect(json_response['diffs']).to be_empty
expect(json_response['compare_same_ref']).to be_truthy
end
it "returns an empty string when the diff overflows" do
stub_const('Gitlab::Git::DiffCollection::DEFAULT_LIMITS', { max_files: 2, max_lines: 2 })
get api(route, current_user), params: { from: 'master', to: 'feature' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['commits']).to be_present
expect(json_response['diffs']).to be_present
expect(json_response['diffs'].first['diff']).to be_empty
end
it "returns a 404 when from ref is unknown" do
get api(route, current_user), params: { from: 'unknown_ref', to: 'master' }
expect(response).to have_gitlab_http_status(404)
end
it "returns a 404 when to ref is unknown" do
get api(route, current_user), params: { from: 'master', to: 'unknown_ref' }
expect(response).to have_gitlab_http_status(404)
end
end
context 'when unauthenticated', 'and project is public' do
......
......@@ -986,10 +986,10 @@
"@sentry/types" "5.10.0"
tslib "^1.9.3"
"@sourcegraph/code-host-integration@^0.0.18":
version "0.0.18"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.18.tgz#814467cdbc94bbfee5768193acf89fdf404ca949"
integrity sha512-PNKR6QI2MK17YJ4BBmWBz7SVRPIJZKbGkQpdB9jHsvQhdSxspdpWFaMu+HKeg96zpStdLhFOcDPn1wlKbdGy+w==
"@sourcegraph/code-host-integration@0.0.21":
version "0.0.21"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.21.tgz#d536ccb3d9fda6d0c9d611ed6b80813265d8cb2f"
integrity sha512-HRBb6FO5+kc0JM6mAzhBGrDCuMdkGBjgdnKGnkW8B/FFKEtZEB6HI4ghGfY0eH01tFRis7snkZ4b3NSLjAbHew==
"@types/anymatch@*":
version "1.3.0"
......@@ -1153,21 +1153,6 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
"@vue/component-compiler-utils@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz#d16fa26b836c06df5baaeb45f3d80afc47e35634"
integrity sha512-am+04/0UX7ektcmvhYmrf84BDVAD8afFOf4asZjN84q8xzxFclbk5x0MtxuKGfp+zjN5WWPJn3fjFAWtDdIGSw==
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
lru-cache "^4.1.2"
merge-source-map "^1.1.0"
postcss "^7.0.14"
postcss-selector-parser "^5.0.0"
prettier "1.16.3"
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
"@vue/component-compiler-utils@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.1.1.tgz#d4ef8f80292674044ad6211e336a302e4d2a6575"
......@@ -2087,16 +2072,11 @@ bootstrap-vue@2.0.0-rc.27:
portal-vue "^2.1.5"
vue-functional-data-merge "^3.1.0"
bootstrap@4.3.1:
bootstrap@4.3.1, bootstrap@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac"
integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==
bootstrap@^4.3.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
boxen@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
......@@ -5520,12 +5500,7 @@ he@^1.1.0, he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
highlight.js@^9.13.1:
version "9.18.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.0.tgz#6b1763cfcd53744313bd3f31f1210f7beb962c79"
integrity sha512-A97kI1KAUzKoAiEoaGcf2O9YPS8nbDTCRFokaaeBhnqjQTvbAuAJrQMm21zw8s8xzaMtCQBtgbyGXLGxdxQyqQ==
highlight.js@~9.13.0:
highlight.js@^9.13.1, highlight.js@~9.13.0:
version "9.13.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
......@@ -6803,18 +6778,7 @@ js-base64@^2.1.8:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
js-beautify@^1.6.12:
version "1.10.2"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178"
integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==
dependencies:
config-chain "^1.1.12"
editorconfig "^0.15.3"
glob "^7.1.3"
mkdirp "~0.5.1"
nopt "~4.0.1"
js-beautify@^1.8.8:
js-beautify@^1.6.12, js-beautify@^1.8.8:
version "1.10.3"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1"
integrity sha512-wfk/IAWobz1TfApSdivH5PJ0miIHgDoYb1ugSqHcODPmaYu46rYe5FVuIEkhjg8IQiv6rDNPyhsqbsohI/C2vQ==
......@@ -8836,12 +8800,7 @@ pofile@^1:
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg==
popper.js@^1.14.7:
version "1.15.0"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2"
integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==
popper.js@^1.15.0:
popper.js@^1.14.7, popper.js@^1.15.0:
version "1.16.0"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3"
integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==
......@@ -9042,16 +9001,11 @@ prettier@1.16.3:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d"
integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==
prettier@1.18.2:
prettier@1.18.2, prettier@^1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
prettier@^1.18.2:
version "1.19.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
pretty-format@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2"
......@@ -11759,7 +11713,7 @@ vue-jest@^4.0.0-beta.2:
source-map "^0.5.6"
ts-jest "^23.10.5"
vue-loader@^15.4.2:
vue-loader@^15.4.2, vue-loader@^15.7.1:
version "15.8.3"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.8.3.tgz#857cb9e30eb5fc25e66db48dce7e4f768602a23c"
integrity sha512-yFksTFbhp+lxlm92DrKdpVIWMpranXnTEuGSc0oW+Gk43M9LWaAmBTnfj5+FCdve715mTHvo78IdaXf5TbiTJg==
......@@ -11770,17 +11724,6 @@ vue-loader@^15.4.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-loader@^15.7.1:
version "15.7.1"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.1.tgz#6ccacd4122aa80f69baaac08ff295a62e3aefcfd"
integrity sha512-fwIKtA23Pl/rqfYP5TSGK7gkEuLhoTvRYW+TU7ER3q9GpNLt/PjG5NLv3XHRDiTg7OPM1JcckBgds+VnAc+HbA==
dependencies:
"@vue/component-compiler-utils" "^3.0.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-router@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment