diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index 8c2fb98a120c2f5ee1e77f2b2c332eb37f4307c8..d5e98228ddc91e948e831b7b1e96b6f5687b7455 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -5,7 +5,9 @@ module Projects
     
       before_action :authorize_read_cycle_analytics!
       before_action :authorize_builds!, only: [:test, :staging]
-    
+      before_action :authorize_read_issue!, only: [:issue, :production]
+      before_action :authorize_read_merge_request!, only: [:code, :review]
+
       def issue
         render_events(events.issue_events)
       end
@@ -60,7 +62,11 @@ module Projects
       end
     
       def authorize_builds!
-        return access_denied! unless current_user.can?(:read_build, project)
+        return access_denied! unless can?(current_user, :read_build, project)
+      end
+
+      def authorize_read_issue!
+        return access_denied! unless can?(current_user, :read_issue, project)
       end
     end
   end
diff --git a/lib/gitlab/cycle_analytics/author_updater.rb b/lib/gitlab/cycle_analytics/author_updater.rb
index ab18f292bc3ced7f00afd2138af53f9545b5ecb7..87d26701d3a5e7bf0b82fb7fd4b36b3fe0511b82 100644
--- a/lib/gitlab/cycle_analytics/author_updater.rb
+++ b/lib/gitlab/cycle_analytics/author_updater.rb
@@ -1,26 +1,8 @@
 module Gitlab
   module CycleAnalytics
-    class AuthorUpdater
-      def self.update!(*args)
-        new(*args).update!
-      end
-
-      def initialize(event_result)
-        @event_result = event_result
-      end
-
-      def update!
-        @event_result.each do |event|
-          event['author'] = users[event.delete('author_id').to_i].first
-        end
-      end
-
-      def user_ids
-        @event_result.map { |event| event['author_id'] }
-      end
-
-      def users
-        @users ||= User.find(user_ids).group_by { |user| user['id'] }
+    class AuthorUpdater < Updater
+      def self.update!(event_result)
+        new(event_result, User, :author).update!
       end
     end
   end
diff --git a/lib/gitlab/cycle_analytics/build_updater.rb b/lib/gitlab/cycle_analytics/build_updater.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c1190d9e7a97a13f60ea2c98cc98c9f4b13011c0
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/build_updater.rb
@@ -0,0 +1,9 @@
+module Gitlab
+  module CycleAnalytics
+    class BuildUpdater < Updater
+      def self.update!(event_result)
+        new(event_result, ::Ci::Build, :build, 'id').update!
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/cycle_analytics/code_event.rb b/lib/gitlab/cycle_analytics/code_event.rb
index 02a3a44d544d15b9f965f93cc21b2b86058ce9bd..2afdf0b8518b487d643c77fb77694373db601953 100644
--- a/lib/gitlab/cycle_analytics/code_event.rb
+++ b/lib/gitlab/cycle_analytics/code_event.rb
@@ -1,6 +1,8 @@
 module Gitlab
   module CycleAnalytics
     class CodeEvent < BaseEvent
+      include MergeRequestAllowed
+
       def initialize(*args)
         @stage = :code
         @start_time_attrs = issue_metrics_table[:first_mentioned_in_commit_at]
@@ -21,10 +23,6 @@ module Gitlab
       def serialize(event)
         AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json
       end
-
-      def allowed_ids
-        @allowed_ids ||= MergeRequestsFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
-      end
     end
   end
 end
diff --git a/lib/gitlab/cycle_analytics/issue_allowed.rb b/lib/gitlab/cycle_analytics/issue_allowed.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a7652a7064193adcd78e9c0be82ca5861fdeaa3c
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/issue_allowed.rb
@@ -0,0 +1,9 @@
+module Gitlab
+  module CycleAnalytics
+    module IssueAllowed
+      def allowed_ids
+        @allowed_ids ||= IssuesFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/cycle_analytics/issue_event.rb b/lib/gitlab/cycle_analytics/issue_event.rb
index 36a990d62225877267cadd0a9db35b4033302abd..705b7e5ce24871addc58d903a45f25b52b878a4f 100644
--- a/lib/gitlab/cycle_analytics/issue_event.rb
+++ b/lib/gitlab/cycle_analytics/issue_event.rb
@@ -1,6 +1,8 @@
 module Gitlab
   module CycleAnalytics
     class IssueEvent < BaseEvent
+      include IssueAllowed
+
       def initialize(*args)
         @stage = :issue
         @start_time_attrs = issue_table[:created_at]
@@ -20,10 +22,6 @@ module Gitlab
       def serialize(event)
         AnalyticsIssueSerializer.new(project: @project).represent(event).as_json
       end
-
-      def allowed_ids
-        @allowed_ids ||= IssuesFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
-      end
     end
   end
 end
diff --git a/lib/gitlab/cycle_analytics/merge_request_allowed.rb b/lib/gitlab/cycle_analytics/merge_request_allowed.rb
new file mode 100644
index 0000000000000000000000000000000000000000..28f6db447594864e0f0b667b6e4ff67b58b75896
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/merge_request_allowed.rb
@@ -0,0 +1,9 @@
+module Gitlab
+  module CycleAnalytics
+    module MergeRequestAllowed
+      def allowed_ids
+        @allowed_ids ||= MergeRequestsFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/cycle_analytics/production_event.rb b/lib/gitlab/cycle_analytics/production_event.rb
index fcf2dbe349045b8fcbb769bf93edbdddb7aedca6..4868c3c62373d942bea2d10bade2160cfbf1969e 100644
--- a/lib/gitlab/cycle_analytics/production_event.rb
+++ b/lib/gitlab/cycle_analytics/production_event.rb
@@ -1,6 +1,8 @@
 module Gitlab
   module CycleAnalytics
     class ProductionEvent < BaseEvent
+      include IssueAllowed
+
       def initialize(*args)
         @stage = :production
         @start_time_attrs = issue_table[:created_at]
@@ -19,10 +21,6 @@ module Gitlab
       def serialize(event)
         AnalyticsIssueSerializer.new(project: @project).represent(event).as_json
       end
-
-      def allowed_ids
-        @allowed_ids ||= IssuesFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
-      end
     end
   end
 end
diff --git a/lib/gitlab/cycle_analytics/review_event.rb b/lib/gitlab/cycle_analytics/review_event.rb
index 30650537afe8716c007eba21a07971918f9f38ad..b394a02cc529f173f578e2d66490b91f649b6c0e 100644
--- a/lib/gitlab/cycle_analytics/review_event.rb
+++ b/lib/gitlab/cycle_analytics/review_event.rb
@@ -1,6 +1,8 @@
 module Gitlab
   module CycleAnalytics
     class ReviewEvent < BaseEvent
+      include MergeRequestAllowed
+
       def initialize(*args)
         @stage = :review
         @start_time_attrs = mr_table[:created_at]
@@ -18,10 +20,6 @@ module Gitlab
       def serialize(event)
         AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json
       end
-
-      def allowed_ids
-        @allowed_ids ||= MergeRequestsFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
-      end
     end
   end
 end
diff --git a/lib/gitlab/cycle_analytics/staging_event.rb b/lib/gitlab/cycle_analytics/staging_event.rb
index 800b2b786dddc763eb509143a83cc37abd30c632..6c42b1a3a603b661ff30c80816171515744952c6 100644
--- a/lib/gitlab/cycle_analytics/staging_event.rb
+++ b/lib/gitlab/cycle_analytics/staging_event.rb
@@ -11,6 +11,12 @@ module Gitlab
         super(*args)
       end
 
+      def fetch
+        BuildUpdater.update!(event_result)
+
+        super
+      end
+
       def custom_query(base_query)
         base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
       end
@@ -18,9 +24,7 @@ module Gitlab
       private
 
       def serialize(event)
-        build = ::Ci::Build.find(event['id'])
-
-        AnalyticsBuildSerializer.new.represent(build).as_json
+        AnalyticsBuildSerializer.new.represent(event['build']).as_json
       end
     end
   end
diff --git a/lib/gitlab/cycle_analytics/updater.rb b/lib/gitlab/cycle_analytics/updater.rb
new file mode 100644
index 0000000000000000000000000000000000000000..38cbfa030302b17e29f1c88e0c210cbde5323763
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/updater.rb
@@ -0,0 +1,30 @@
+module Gitlab
+  module CycleAnalytics
+    class Updater
+      def self.update!(*args)
+        new(*args).update!
+      end
+
+      def initialize(event_result, update_klass, update_key, column = nil)
+        @event_result = event_result
+        @update_klass = update_klass
+        @update_key = update_key.to_s
+        @column = column || "#{@update_key}_id"
+      end
+
+      def update!
+        @event_result.each do |event|
+          event[@update_key] = items[event.delete(@column).to_i].first
+        end
+      end
+
+      def result_ids
+        @event_result.map { |event| event[@column] }
+      end
+
+      def items
+        @items ||= @update_klass.find(result_ids).group_by { |item| item['id'] }
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f9e4d1714e62540ac553f25791736ad224b93702
--- /dev/null
+++ b/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe Gitlab::CycleAnalytics::AuthorUpdater do
+  let(:user) { create(:user) }
+  let(:events) { [{ 'author_id' => user.id }] }
+
+  it 'maps the correct user' do
+    described_class.update!(events)
+
+    expect(events.first['author']).to eq(user)
+  end
+end
diff --git a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8e461f6c6ea1250cdbf4496ec6e63771b46b8717
--- /dev/null
+++ b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe Gitlab::CycleAnalytics::BuildUpdater do
+  let(:build) { create(:ci_build) }
+  let(:events) { [{ 'id' => build.id }] }
+
+  it 'maps the correct user' do
+    described_class.update!(events)
+
+    expect(events.first['build']).to eq(build)
+  end
+end