mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-25 17:08:32 +00:00
Add latest changes from gitlab-org/security/gitlab@17-11-stable-ee
This commit is contained in:
@ -10,11 +10,11 @@ import {
|
||||
export const getRoleDropdownItems = roleDropdownItems;
|
||||
export const getMemberRole = initialSelectedRole;
|
||||
|
||||
// The API to update members uses different property names for the access level, depending on if it's a user or a group.
|
||||
// Users use 'access_level', groups use 'group_access'.
|
||||
// The API to update members uses different property names for the access level, depending on each member's namespace
|
||||
const ACCESS_LEVEL_PROPERTY_NAME = {
|
||||
[MEMBERS_TAB_TYPES.user]: MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
|
||||
[MEMBERS_TAB_TYPES.group]: GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
|
||||
[MEMBERS_TAB_TYPES.accessRequest]: MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
|
||||
};
|
||||
|
||||
export const callRoleUpdateApi = async (member, role) => {
|
||||
|
@ -2,10 +2,40 @@
|
||||
|
||||
class CertificateFingerprintValidator < ActiveModel::EachValidator
|
||||
FINGERPRINT_PATTERN = /\A([a-zA-Z0-9]{2}[\s\-:]?){16,}\z/
|
||||
SHA1_FINGERPRINT_PATTERN = /\A(?:(?:[A-Fa-f0-9]{2}[\s:]){19}[A-Fa-f0-9]{2}|[A-Fa-f0-9]{40})\z/
|
||||
SHA256_FINGERPRINT_PATTERN = /\A(?:(?:[A-Fa-f0-9]{2}[\s:]){31}[A-Fa-f0-9]{2}|[A-Fa-f0-9]{64})\z/
|
||||
MIN_LENGTH = 40
|
||||
MAX_LENGTH = 95
|
||||
|
||||
def validate_each(record, attribute, value)
|
||||
# We introduce the new validation logic only for new records and updates that will change the attribute
|
||||
# in order to limit the impact on existing invalid records.
|
||||
if record.new_record? || record.will_save_change_to_attribute?(attribute)
|
||||
validate_sha1_or_sha256_pattern(record, attribute, value)
|
||||
else
|
||||
validate_length_and_pattern(record, attribute, value)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_sha1_or_sha256_pattern(record, attribute, value)
|
||||
unless within_length_limits?(value) && matches_sha1_or_sha256_pattern?(value)
|
||||
record.errors.add(attribute, "must be 40 or 64 hex characters (with optional colons between pairs)")
|
||||
end
|
||||
end
|
||||
|
||||
def validate_length_and_pattern(record, attribute, value)
|
||||
unless value.try(:match, FINGERPRINT_PATTERN)
|
||||
record.errors.add(attribute, "must be a hash containing only letters, numbers, spaces, : and -")
|
||||
end
|
||||
end
|
||||
|
||||
def within_length_limits?(value)
|
||||
value.try(:length) && value.length >= MIN_LENGTH && value.length <= MAX_LENGTH
|
||||
end
|
||||
|
||||
def matches_sha1_or_sha256_pattern?(value)
|
||||
value.try(:match, SHA1_FINGERPRINT_PATTERN) || value.try(:match, SHA256_FINGERPRINT_PATTERN)
|
||||
end
|
||||
end
|
||||
|
@ -10,6 +10,8 @@ module API
|
||||
filename: API::NO_SLASH_URL_PART_REGEX
|
||||
)
|
||||
|
||||
before { authenticate_non_get! }
|
||||
|
||||
helpers do
|
||||
def find_uploads(parent)
|
||||
uploads = Banzai::UploadsFinder.new(parent: parent).execute
|
||||
|
@ -46889,6 +46889,9 @@ msgstr ""
|
||||
msgid "Project %{code_open}%{source_project}%{code_close} has more restricted access settings than %{code_open}%{target_project}%{code_close}. To avoid exposing private changes, make sure you're submitting changes to the correct project."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project %{project_name} and framework %{framework_name} are not from same namespace."
|
||||
msgstr ""
|
||||
|
||||
msgid "Project %{project_name} and framework are not from same namespace."
|
||||
msgstr ""
|
||||
|
||||
|
@ -34,11 +34,12 @@ describe('Role details drawer utils', () => {
|
||||
|
||||
describe('callRoleUpdateApi', () => {
|
||||
it.each`
|
||||
namespace | propertyName
|
||||
${'user'} | ${'access_level'}
|
||||
${'group'} | ${'group_access'}
|
||||
namespace | propertyName
|
||||
${'user'} | ${'access_level'}
|
||||
${'group'} | ${'group_access'}
|
||||
${'accessRequest'} | ${'access_level'}
|
||||
`(
|
||||
'calls update API with expected data for $namespace namespace',
|
||||
'calls update API with expected data for each member.namespace = $namespace',
|
||||
async ({ namespace, propertyName }) => {
|
||||
const memberPath = 'member/path/123';
|
||||
const mockAxios = new MockAdapter(axios);
|
||||
|
@ -9,6 +9,8 @@ RSpec.describe API::MarkdownUploads, feature_category: :team_planning do
|
||||
let_it_be(:project) { create(:project, :private) }
|
||||
let_it_be(:project_maintainer) { create(:user, maintainer_of: project) }
|
||||
|
||||
let_it_be(:public_project) { create(:project, :public) }
|
||||
|
||||
let_it_be(:user) { create(:user, guest_of: [project, group]) }
|
||||
|
||||
describe "POST /projects/:id/uploads/authorize" do
|
||||
@ -34,6 +36,16 @@ RSpec.describe API::MarkdownUploads, feature_category: :team_planning do
|
||||
end
|
||||
end
|
||||
|
||||
context 'with anonymous user on public project' do
|
||||
let(:project) { public_project }
|
||||
|
||||
it "returns 401" do
|
||||
post api(path), headers: headers
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no Workhorse headers' do
|
||||
it "returns 403" do
|
||||
post api(path, user)
|
||||
@ -47,10 +59,6 @@ RSpec.describe API::MarkdownUploads, feature_category: :team_planning do
|
||||
let(:file) { fixture_file_upload("spec/fixtures/dk.png", "image/png") }
|
||||
let(:path) { "/projects/#{project.id}/uploads" }
|
||||
|
||||
before do
|
||||
project
|
||||
end
|
||||
|
||||
it "uploads the file through the upload service and returns its info" do
|
||||
expect(UploadService).to receive(:new).with(project, anything, uploaded_by_user_id: user.id).and_call_original
|
||||
|
||||
@ -82,6 +90,16 @@ RSpec.describe API::MarkdownUploads, feature_category: :team_planning do
|
||||
expect(tempfile.path).to be_nil
|
||||
expect(File.exist?(path)).to be(false)
|
||||
end
|
||||
|
||||
context 'with anonymous user on public project' do
|
||||
let(:project) { public_project }
|
||||
|
||||
it "returns 401" do
|
||||
post api(path), params: { file: file }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'an unauthorized request' do
|
||||
|
Reference in New Issue
Block a user