Class: Gitlab::Auth::Identity
- Inherits:
-
Object
- Object
- Gitlab::Auth::Identity
- Defined in:
- lib/gitlab/auth/identity.rb
Overview
Identity class represents identity which we want to use in authorization policies.
It decides if an identity is a single or composite identity and finds identity scope.
Constant Summary collapse
- COMPOSITE_IDENTITY_USERS_KEY =
'composite_identities'- COMPOSITE_IDENTITY_KEY_FORMAT =
'user:%s:composite_identity'- COMPOSITE_IDENTITY_SIDEKIQ_ARG =
Sidekiq Composite Identity
'sqci'- IdentityError =
Class.new(StandardError)
- IdentityLinkMismatchError =
Class.new(IdentityError)
- UnexpectedIdentityError =
Class.new(IdentityError)
- TooManyIdentitiesLinkedError =
Class.new(IdentityError)
- MissingCompositeIdentityError =
Class.new(::Gitlab::Access::AccessDeniedError)
- MissingServiceAccountError =
Class.new(::Gitlab::Access::AccessDeniedError)
Class Method Summary collapse
- .currently_linked ⇒ Object
- .fabricate(user) ⇒ Object
- .find_primary_user_by_scoped_user_id(scoped_user_id, store: ::Gitlab::SafeRequestStore) ⇒ Object
- .invert_composite_identity(current_user) ⇒ Object
- .link_from_job(job) ⇒ Object
-
.link_from_oauth_token(oauth_token) ⇒ Object
TODO: why is this called 3 times in doorkeeper_access_spec.rb specs?.
- .link_from_scoped_user(user, scoped_user) ⇒ Object
- .link_from_scoped_user_id(user, scoped_user_id) ⇒ Object
- .link_from_web_request(service_account:, scoped_user:) ⇒ Object
- .sidekiq_restore!(job) ⇒ Object
Instance Method Summary collapse
- #composite? ⇒ Boolean
-
#initialize(user, store: ::Gitlab::SafeRequestStore) ⇒ Identity
constructor
A new instance of Identity.
- #link!(scope_user) ⇒ Object
- #linked? ⇒ Boolean
- #primary_user ⇒ Object
- #scoped_user ⇒ Object
- #sidekiq_link!(job) ⇒ Object
- #valid? ⇒ Boolean
Constructor Details
#initialize(user, store: ::Gitlab::SafeRequestStore) ⇒ Identity
Returns a new instance of Identity.
107 108 109 110 111 112 |
# File 'lib/gitlab/auth/identity.rb', line 107 def initialize(user, store: ::Gitlab::SafeRequestStore) raise UnexpectedIdentityError unless user.is_a?(::User) @user = user @request_store = store end |
Class Method Details
.currently_linked ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/gitlab/auth/identity.rb', line 68 def self.currently_linked user = ::Gitlab::SafeRequestStore .store[COMPOSITE_IDENTITY_USERS_KEY] .to_a.first return unless user.present? identity = new(user) block_given? ? yield(identity) : identity end |
.fabricate(user) ⇒ Object
80 81 82 |
# File 'lib/gitlab/auth/identity.rb', line 80 def self.fabricate(user) new(user) if user.is_a?(::User) end |
.find_primary_user_by_scoped_user_id(scoped_user_id, store: ::Gitlab::SafeRequestStore) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/gitlab/auth/identity.rb', line 84 def self.find_primary_user_by_scoped_user_id(scoped_user_id, store: ::Gitlab::SafeRequestStore) return unless scoped_user_id # Get all composite identities from the store composite_identities = store.store[COMPOSITE_IDENTITY_USERS_KEY] || Set.new # Check each composite identity to find the one with matching scoped user composite_identities.find do |primary_user| identity_key = format(COMPOSITE_IDENTITY_KEY_FORMAT, primary_user.id) scoped_user = store.store[identity_key] scoped_user&.id == scoped_user_id end end |
.invert_composite_identity(current_user) ⇒ Object
99 100 101 102 103 104 105 |
# File 'lib/gitlab/auth/identity.rb', line 99 def self.invert_composite_identity(current_user) return unless current_user primary_user = Gitlab::Auth::Identity.find_primary_user_by_scoped_user_id(current_user.id) primary_user || current_user end |
.link_from_job(job) ⇒ Object
29 30 31 32 33 |
# File 'lib/gitlab/auth/identity.rb', line 29 def self.link_from_job(job) fabricate(job.user).tap do |identity| identity.link!(job.scoped_user) if identity&.composite? end end |
.link_from_oauth_token(oauth_token) ⇒ Object
TODO: why is this called 3 times in doorkeeper_access_spec.rb specs?
23 24 25 26 27 |
# File 'lib/gitlab/auth/identity.rb', line 23 def self.link_from_oauth_token(oauth_token) fabricate(oauth_token.user).tap do |identity| identity.link!(oauth_token.scope_user) if identity&.composite? end end |
.link_from_scoped_user(user, scoped_user) ⇒ Object
43 44 45 46 47 |
# File 'lib/gitlab/auth/identity.rb', line 43 def self.link_from_scoped_user(user, scoped_user) ::Gitlab::Auth::Identity.fabricate(user).tap do |identity| identity.link!(scoped_user) if identity&.composite? end end |
.link_from_scoped_user_id(user, scoped_user_id) ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/gitlab/auth/identity.rb', line 35 def self.link_from_scoped_user_id(user, scoped_user_id) scoped_user = ::User.find_by_id(scoped_user_id) return unless scoped_user ::Gitlab::Auth::Identity.link_from_scoped_user(user, scoped_user) end |
.link_from_web_request(service_account:, scoped_user:) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/gitlab/auth/identity.rb', line 49 def self.link_from_web_request(service_account:, scoped_user:) raise MissingServiceAccountError, 'service account is required' unless service_account fabricate(service_account).tap do |identity| identity.link!(scoped_user) if identity&.composite? end end |
.sidekiq_restore!(job) ⇒ Object
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/gitlab/auth/identity.rb', line 57 def self.sidekiq_restore!(job) ids = Array(job[COMPOSITE_IDENTITY_SIDEKIQ_ARG]) return if ids.empty? raise IdentityError, 'unexpected number of identities in Sidekiq job' unless ids.size == 2 ::Gitlab::Auth::Identity .new(::User.find(ids.first)) .link!(::User.find(ids.second)) end |
Instance Method Details
#composite? ⇒ Boolean
114 115 116 |
# File 'lib/gitlab/auth/identity.rb', line 114 def composite? @user.composite_identity_enforced? end |
#link!(scope_user) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/gitlab/auth/identity.rb', line 122 def link!(scope_user) return self unless scope_user ## # TODO: consider extracting linking to ::Gitlab::Auth::Identities::Link#create! # validate_link!(scope_user) store_identity_link!(scope_user) append_log!(scope_user) self end |
#linked? ⇒ Boolean
135 136 137 |
# File 'lib/gitlab/auth/identity.rb', line 135 def linked? @request_store.exist?(store_key) end |
#primary_user ⇒ Object
153 154 155 |
# File 'lib/gitlab/auth/identity.rb', line 153 def primary_user @user end |
#scoped_user ⇒ Object
147 148 149 150 151 |
# File 'lib/gitlab/auth/identity.rb', line 147 def scoped_user @request_store.fetch(store_key) do raise MissingCompositeIdentityError, 'composite identity missing' end end |
#sidekiq_link!(job) ⇒ Object
118 119 120 |
# File 'lib/gitlab/auth/identity.rb', line 118 def sidekiq_link!(job) job[COMPOSITE_IDENTITY_SIDEKIQ_ARG] = [primary_user_id, scoped_user_id] end |
#valid? ⇒ Boolean
139 140 141 142 143 144 145 |
# File 'lib/gitlab/auth/identity.rb', line 139 def valid? return true unless composite? return false unless linked? !scoped_user.composite_identity_enforced? end |