diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-14 12:06:30 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-14 12:06:30 +0000 |
commit | d8c06be498acbfc2024c01b6b6b02d120dc499f2 (patch) | |
tree | 9e2e0852c45332d6222898676a2f6f096e600084 /spec/support/helpers/access_matchers_helpers.rb | |
parent | 2fa7d2ddf6a7004f89616e43b8279229af831e25 (diff) | |
download | gitlab-ce-d8c06be498acbfc2024c01b6b6b02d120dc499f2.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/support/helpers/access_matchers_helpers.rb')
-rw-r--r-- | spec/support/helpers/access_matchers_helpers.rb | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/spec/support/helpers/access_matchers_helpers.rb b/spec/support/helpers/access_matchers_helpers.rb new file mode 100644 index 00000000000..9100f245d36 --- /dev/null +++ b/spec/support/helpers/access_matchers_helpers.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module AccessMatchersHelpers + USER_ACCESSOR_METHOD_NAME = 'user' + + def provide_user(role, membership = nil) + case role + when :admin + create(:admin) + when :auditor + create(:user, :auditor) + when :user + create(:user) + when :external + create(:user, :external) + when :visitor, :anonymous + nil + when User + role + when *Gitlab::Access.sym_options_with_owner.keys # owner, maintainer, developer, reporter, guest + raise ArgumentError, "cannot provide #{role} when membership reference is blank" unless membership + + provide_user_by_membership(role, membership) + else + raise ArgumentError, "cannot provide user of an unknown role #{role}" + end + end + + def provide_user_by_membership(role, membership) + if role == :owner && membership.owner + membership.owner + else + create(:user).tap do |user| + membership.public_send(:"add_#{role}", user) + end + end + end + + def raise_if_non_block_expectation!(actual) + raise ArgumentError, 'This matcher supports block expectations only.' unless actual.is_a?(Proc) + end + + def update_owner(objects, user) + return unless objects + + objects.each do |object| + if object.respond_to?(:owner) + object.update_attribute(:owner, user) + elsif object.respond_to?(:user) + object.update_attribute(:user, user) + else + raise ArgumentError, "cannot own this object #{object}" + end + end + end + + def patch_example_group(user) + return if user.nil? # for anonymous users + + # This call is evaluated in context of ExampleGroup instance in which the matcher is called. Overrides the `user` + # (or defined by `method_name`) method generated by `let` definition in example group before it's used by `subject`. + # This override is per concrete example only because the example group class gets re-created for each example. + instance_eval(<<~CODE, __FILE__, __LINE__ + 1) + if instance_variable_get(:@__#{USER_ACCESSOR_METHOD_NAME}_patched) + raise ArgumentError, 'An access matcher be_allowed_for/be_denied_for can be used only once per example (`it` block)' + end + instance_variable_set(:@__#{USER_ACCESSOR_METHOD_NAME}_patched, true) + + def #{USER_ACCESSOR_METHOD_NAME} + @#{USER_ACCESSOR_METHOD_NAME} ||= User.find(#{user.id}) + end + CODE + end + + def prepare_matcher_environment(role, membership, owned_objects) + user = provide_user(role, membership) + + if user + update_owner(owned_objects, user) + patch_example_group(user) + end + end + + def run_matcher(action, role, membership, owned_objects) + raise_if_non_block_expectation!(action) + + prepare_matcher_environment(role, membership, owned_objects) + + if block_given? + yield action + else + action.call + end + end +end |