X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/431b8df752ca99dd8aa777864f7c5ada650d0ac9..053f74285455278bed87cd4b3dc0df2adffb3b9c:/services/api/app/models/api_client_authorization.rb diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb index 52f2cee064..a6beaa07ab 100644 --- a/services/api/app/models/api_client_authorization.rb +++ b/services/api/app/models/api_client_authorization.rb @@ -111,6 +111,30 @@ class ApiClientAuthorization < ArvadosModel clnt end + def self.check_anonymous_user_token token + case token[0..2] + when 'v2/' + _, token_uuid, secret, optional = token.split('/') + unless token_uuid.andand.length == 27 && secret.andand.length.andand > 0 + # invalid token + return nil + end + else + # v1 token + secret = token + end + + # The anonymous token content and minimum length is verified in lib/config + if secret.length >= 0 && secret == Rails.configuration.Users.AnonymousUserToken + return ApiClientAuthorization.new(user: User.find_by_uuid(anonymous_user_uuid), + uuid: Rails.configuration.ClusterID+"-gj3su-anonymouspublic", + api_token: token, + api_client: anonymous_user_token_api_client) + else + return nil + end + end + def self.check_system_root_token token if token == Rails.configuration.SystemRootToken return ApiClientAuthorization.new(user: User.find_by_uuid(system_user_uuid), @@ -126,6 +150,11 @@ class ApiClientAuthorization < ArvadosModel return nil if token.nil? or token.empty? remote ||= Rails.configuration.ClusterID + auth = self.check_anonymous_user_token(token) + if !auth.nil? + return auth + end + auth = self.check_system_root_token(token) if !auth.nil? return auth @@ -319,7 +348,17 @@ class ApiClientAuthorization < ArvadosModel user.last_name = "from cluster #{remote_user_prefix}" end - user.save! + begin + user.save! + rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique + Rails.logger.debug("remote user #{remote_user['uuid']} already exists, retrying...") + # Some other request won the race: retry fetching the user record. + user = User.find_by_uuid(remote_user['uuid']) + if !user + Rails.logger.warn("cannot find or create remote user #{remote_user['uuid']}") + return nil + end + end if user.is_invited && !remote_user['is_invited'] # Remote user is not "invited" state, they should be unsetup, which @@ -364,12 +403,24 @@ class ApiClientAuthorization < ArvadosModel exp = [db_current_time + Rails.configuration.Login.RemoteTokenRefresh, remote_token.andand['expires_at']].compact.min scopes = remote_token.andand['scopes'] || ['all'] - auth = ApiClientAuthorization.find_or_create_by(uuid: token_uuid) do |auth| - auth.user = user - auth.api_token = stored_secret - auth.api_client_id = 0 - auth.scopes = scopes - auth.expires_at = exp + begin + retries ||= 0 + auth = ApiClientAuthorization.find_or_create_by(uuid: token_uuid) do |auth| + auth.user = user + auth.api_token = stored_secret + auth.api_client_id = 0 + auth.scopes = scopes + auth.expires_at = exp + end + rescue ActiveRecord::RecordNotUnique + Rails.logger.debug("cached remote token #{token_uuid} already exists, retrying...") + # Some other request won the race: retry just once before erroring out + if (retries += 1) <= 1 + retry + else + Rails.logger.warn("cannot find or create cached remote token #{token_uuid}") + return nil + end end auth.update_attributes!(user: user, api_token: stored_secret,