summaryrefslogtreecommitdiff
path: root/lib/api/helpers.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/api/helpers.rb')
-rw-r--r--lib/api/helpers.rb95
1 files changed, 63 insertions, 32 deletions
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 130509cdad6..714d4ea3dc6 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -12,13 +12,30 @@ module API
nil
end
+ def private_token
+ params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]
+ end
+
+ def warden
+ env['warden']
+ end
+
+ # Check the Rails session for valid authentication details
+ def find_user_from_warden
+ warden ? warden.authenticate : nil
+ end
+
def find_user_by_private_token
- token_string = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
- User.find_by_authentication_token(token_string) || User.find_by_personal_access_token(token_string)
+ token = private_token
+ return nil unless token.present?
+
+ User.find_by_authentication_token(token) || User.find_by_personal_access_token(token)
end
def current_user
- @current_user ||= (find_user_by_private_token || doorkeeper_guard)
+ @current_user ||= find_user_by_private_token
+ @current_user ||= doorkeeper_guard
+ @current_user ||= find_user_from_warden
unless @current_user && Gitlab::UserAccess.new(@current_user).allowed?
return nil
@@ -28,7 +45,7 @@ module API
# If the sudo is the current user do nothing
if identifier && !(@current_user.id == identifier || @current_user.username == identifier)
- render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
+ forbidden!('Must be admin to use sudo') unless @current_user.is_admin?
@current_user = User.by_username_or_id(identifier)
not_found!("No user id or username for: #{identifier}") if @current_user.nil?
end
@@ -49,16 +66,15 @@ module API
def user_project
@project ||= find_project(params[:id])
- @project || not_found!("Project")
end
def find_project(id)
project = Project.find_with_namespace(id) || Project.find_by(id: id)
- if project && can?(current_user, :read_project, project)
+ if can?(current_user, :read_project, project)
project
else
- nil
+ not_found!('Project')
end
end
@@ -89,11 +105,7 @@ module API
end
def find_group(id)
- begin
- group = Group.find(id)
- rescue ActiveRecord::RecordNotFound
- group = Group.find_by!(path: id)
- end
+ group = Group.find_by(path: id) || Group.find_by(id: id)
if can?(current_user, :read_group, group)
group
@@ -134,8 +146,8 @@ module API
forbidden! unless current_user.is_admin?
end
- def authorize!(action, subject)
- forbidden! unless abilities.allowed?(current_user, action, subject)
+ def authorize!(action, subject = nil)
+ forbidden! unless can?(current_user, action, subject)
end
def authorize_push_project
@@ -153,7 +165,7 @@ module API
end
def can?(object, action, subject)
- abilities.allowed?(object, action, subject)
+ Ability.allowed?(object, action, subject)
end
# Checks the occurrences of required attributes, each attribute must be present in the params hash
@@ -197,10 +209,6 @@ module API
errors
end
- def validate_access_level?(level)
- Gitlab::Access.options_with_owner.values.include? level.to_i
- end
-
# Checks the occurrences of datetime attributes, each attribute if present in the params hash must be in ISO 8601
# format (YYYY-MM-DDTHH:MM:SSZ) or a Bad Request error is invoked.
#
@@ -278,6 +286,10 @@ module API
render_api_error!('304 Not Modified', 304)
end
+ def no_content!
+ render_api_error!('204 No Content', 204)
+ end
+
def render_validation_error!(model)
if model.errors.any?
render_api_error!(model.errors.messages || '400 Bad Request', 400)
@@ -288,6 +300,24 @@ module API
error!({ 'message' => message }, status)
end
+ def handle_api_exception(exception)
+ if sentry_enabled? && report_exception?(exception)
+ define_params_for_grape_middleware
+ sentry_context
+ Raven.capture_exception(exception)
+ end
+
+ # lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60
+ trace = exception.backtrace
+
+ message = "\n#{exception.class} (#{exception.message}):\n"
+ message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
+ message << " " << trace.join("\n ")
+
+ API.logger.add Logger::FATAL, message
+ rack_response({ 'message' => '500 Internal Server Error' }.to_json, 500)
+ end
+
# Projects helpers
def filter_projects(projects)
@@ -399,23 +429,10 @@ module API
links.join(', ')
end
- def abilities
- @abilities ||= begin
- abilities = Six.new
- abilities << Ability
- abilities
- end
- end
-
def secret_token
File.read(Gitlab.config.gitlab_shell.secret_file).chomp
end
- def handle_member_errors(errors)
- error!(errors[:access_level], 422) if errors[:access_level].any?
- not_found!(errors)
- end
-
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
@@ -433,5 +450,19 @@ module API
Entities::Issue
end
end
+
+ # The Grape Error Middleware only has access to env but no params. We workaround this by
+ # defining a method that returns the right value.
+ def define_params_for_grape_middleware
+ self.define_singleton_method(:params) { Rack::Request.new(env).params.symbolize_keys }
+ end
+
+ # We could get a Grape or a standard Ruby exception. We should only report anything that
+ # is clearly an error.
+ def report_exception?(exception)
+ return true unless exception.respond_to?(:status)
+
+ exception.status == 500
+ end
end
end