summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/profiles/avatars_controller.rb1
-rw-r--r--app/controllers/projects/avatars_controller.rb1
-rw-r--r--app/models/event.rb10
-rw-r--r--app/models/issue.rb12
-rw-r--r--app/models/merge_request.rb12
-rw-r--r--app/models/note.rb13
-rw-r--r--app/models/project.rb17
-rw-r--r--app/models/user.rb50
-rw-r--r--app/services/issuable_base_service.rb2
-rw-r--r--app/services/notes/delete_service.rb1
-rw-r--r--app/services/notes/update_service.rb1
-rw-r--r--app/services/projects/transfer_service.rb3
-rw-r--r--app/uploaders/avatar_uploader.rb6
-rw-r--r--app/views/events/_event.html.haml19
-rw-r--r--app/views/events/event/_push.html.haml6
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--app/views/layouts/_user_styles.html.haml24
-rw-r--r--app/workers/authorized_projects_worker.rb23
-rw-r--r--changelogs/unreleased/events-cache-invalidation.yml4
-rw-r--r--changelogs/unreleased/refresh-authorizations-with-lease.yml4
-rw-r--r--db/fixtures/development/04_project.rb1
-rw-r--r--db/fixtures/development/06_teams.rb1
-rw-r--r--db/fixtures/development/17_cycle_analytics.rb1
-rw-r--r--db/fixtures/support/serialized_transaction.rb9
-rw-r--r--doc/development/ux_guide/components.md20
-rw-r--r--doc/development/ux_guide/img/components-anchorlinks.pngbin19948 -> 30089 bytes
-rw-r--r--lib/gitlab/database.rb7
-rw-r--r--spec/models/event_spec.rb18
-rw-r--r--spec/models/user_spec.rb27
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb4
-rw-r--r--spec/workers/authorized_projects_worker_spec.rb23
31 files changed, 129 insertions, 193 deletions
diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb
index f193adb46b4..daa51ae41df 100644
--- a/app/controllers/profiles/avatars_controller.rb
+++ b/app/controllers/profiles/avatars_controller.rb
@@ -4,7 +4,6 @@ class Profiles::AvatarsController < Profiles::ApplicationController
@user.remove_avatar!
@user.save
- @user.reset_events_cache
redirect_to profile_path
end
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
index ada7db3c552..53788687076 100644
--- a/app/controllers/projects/avatars_controller.rb
+++ b/app/controllers/projects/avatars_controller.rb
@@ -20,7 +20,6 @@ class Projects::AvatarsController < Projects::ApplicationController
@project.remove_avatar!
@project.save
- @project.reset_events_cache
redirect_to edit_project_path(@project)
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 21eaca917b8..2662f170765 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -43,12 +43,6 @@ class Event < ActiveRecord::Base
scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
class << self
- def reset_event_cache_for(target)
- Event.where(target_id: target.id, target_type: target.class.to_s).
- order('id DESC').limit(100).
- update_all(updated_at: Time.now)
- end
-
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
def contributions
where("action = ? OR (target_type in (?) AND action in (?))",
@@ -353,6 +347,10 @@ class Event < ActiveRecord::Base
update_all(last_activity_at: created_at)
end
+ def authored_by?(user)
+ user ? author_id == user.id : false
+ end
+
private
def recent_update?
diff --git a/app/models/issue.rb b/app/models/issue.rb
index dd0cb75f9a8..fbf07040301 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -182,18 +182,6 @@ class Issue < ActiveRecord::Base
branches_with_iid - branches_with_merge_request
end
- # Reset issue events cache
- #
- # Since we do cache @event we need to reset cache in special cases:
- # * when an issue is updated
- # Events cache stored like events/23-20130109142513.
- # The cache key includes updated_at timestamp.
- # Thus it will automatically generate a new fragment
- # when the event is updated because the key changes.
- def reset_events_cache
- Event.reset_event_cache_for(self)
- end
-
# To allow polymorphism with MergeRequest.
def source_project
project
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index fdf54cc8a7e..69c6aa700d6 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -605,18 +605,6 @@ class MergeRequest < ActiveRecord::Base
self.target_project.repository.branch_names.include?(self.target_branch)
end
- # Reset merge request events cache
- #
- # Since we do cache @event we need to reset cache in special cases:
- # * when a merge request is updated
- # Events cache stored like events/23-20130109142513.
- # The cache key includes updated_at timestamp.
- # Thus it will automatically generate a new fragment
- # when the event is updated because the key changes.
- def reset_events_cache
- Event.reset_event_cache_for(self)
- end
-
def merge_commit_message
message = "Merge branch '#{source_branch}' into '#{target_branch}'\n\n"
message << "#{title}\n\n"
diff --git a/app/models/note.rb b/app/models/note.rb
index ed4224e3046..5b50ca285c3 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -201,19 +201,6 @@ class Note < ActiveRecord::Base
super(noteable_type.to_s.classify.constantize.base_class.to_s)
end
- # Reset notes events cache
- #
- # Since we do cache @event we need to reset cache in special cases:
- # * when a note is updated
- # * when a note is removed
- # Events cache stored like events/23-20130109142513.
- # The cache key includes updated_at timestamp.
- # Thus it will automatically generate a new fragment
- # when the event is updated because the key changes.
- def reset_events_cache
- Event.reset_event_cache_for(self)
- end
-
def editable?
!system?
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 9256e9ddd95..c61e63461e0 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -976,7 +976,6 @@ class Project < ActiveRecord::Base
begin
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
send_move_instructions(old_path_with_namespace)
- reset_events_cache
@old_path_with_namespace = old_path_with_namespace
@@ -1043,22 +1042,6 @@ class Project < ActiveRecord::Base
attrs
end
- # Reset events cache related to this project
- #
- # Since we do cache @event we need to reset cache in special cases:
- # * when project was moved
- # * when project was renamed
- # * when the project avatar changes
- # Events cache stored like events/23-20130109142513.
- # The cache key includes updated_at timestamp.
- # Thus it will automatically generate a new fragment
- # when the event is updated because the key changes.
- def reset_events_cache
- Event.where(project_id: self.id).
- order('id DESC').limit(100).
- update_all(updated_at: Time.now)
- end
-
def project_member(user)
project_members.find_by(user_id: user)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 513a19d81d2..b54ce14f0bf 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -445,27 +445,21 @@ class User < ActiveRecord::Base
end
def refresh_authorized_projects
- loop do
- begin
- Gitlab::Database.serialized_transaction do
- project_authorizations.delete_all
-
- # project_authorizations_union can return multiple records for the same project/user with
- # different access_level so we take row with the maximum access_level
- project_authorizations.connection.execute <<-SQL
- INSERT INTO project_authorizations (user_id, project_id, access_level)
- SELECT user_id, project_id, MAX(access_level) AS access_level
- FROM (#{project_authorizations_union.to_sql}) sub
- GROUP BY user_id, project_id
- SQL
-
- update_column(:authorized_projects_populated, true) unless authorized_projects_populated
- end
-
- break
- # In the event of a concurrent modification Rails raises StatementInvalid.
- # In this case we want to keep retrying until the transaction succeeds
- rescue ActiveRecord::StatementInvalid
+ transaction do
+ project_authorizations.delete_all
+
+ # project_authorizations_union can return multiple records for the same
+ # project/user with different access_level so we take row with the maximum
+ # access_level
+ project_authorizations.connection.execute <<-SQL
+ INSERT INTO project_authorizations (user_id, project_id, access_level)
+ SELECT user_id, project_id, MAX(access_level) AS access_level
+ FROM (#{project_authorizations_union.to_sql}) sub
+ GROUP BY user_id, project_id
+ SQL
+
+ unless authorized_projects_populated
+ update_column(:authorized_projects_populated, true)
end
end
end
@@ -708,20 +702,6 @@ class User < ActiveRecord::Base
project.project_member(self)
end
- # Reset project events cache related to this user
- #
- # Since we do cache @event we need to reset cache in special cases:
- # * when the user changes their avatar
- # Events cache stored like events/23-20130109142513.
- # The cache key includes updated_at timestamp.
- # Thus it will automatically generate a new fragment
- # when the event is updated because the key changes.
- def reset_events_cache
- Event.where(author_id: id).
- order('id DESC').limit(1000).
- update_all(updated_at: Time.now)
- end
-
def full_website_url
return "http://#{website_url}" if website_url !~ /\Ahttps?:\/\//
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 575795788de..d698b295e6d 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -184,8 +184,6 @@ class IssuableBaseService < BaseService
params[:label_ids] = process_label_ids(params, existing_label_ids: issuable.label_ids)
if params.present? && update_issuable(issuable, params)
- issuable.reset_events_cache
-
# We do not touch as it will affect a update on updated_at field
ActiveRecord::Base.no_touching do
handle_common_system_notes(issuable, old_labels: old_labels)
diff --git a/app/services/notes/delete_service.rb b/app/services/notes/delete_service.rb
index 7f1b30ec84e..a673e8e9dde 100644
--- a/app/services/notes/delete_service.rb
+++ b/app/services/notes/delete_service.rb
@@ -2,7 +2,6 @@ module Notes
class DeleteService < BaseService
def execute(note)
note.destroy
- note.reset_events_cache
end
end
end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index 1361b1e0300..75a4b3ed826 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -5,7 +5,6 @@ module Notes
note.update_attributes(params.merge(updated_by: current_user))
note.create_new_cross_references!(current_user)
- note.reset_events_cache
if note.previous_changes.include?('note')
TodoService.new.update_note(note, current_user)
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 28470f59807..34ec575e808 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -61,9 +61,6 @@ module Projects
# Move missing group labels to project
Labels::TransferService.new(current_user, old_group, project).execute
- # clear project cached events
- project.reset_events_cache
-
# Move uploads
Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path)
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
index 71ff14a3f20..38683fdf6d7 100644
--- a/app/uploaders/avatar_uploader.rb
+++ b/app/uploaders/avatar_uploader.rb
@@ -3,16 +3,10 @@ class AvatarUploader < CarrierWave::Uploader::Base
storage :file
- after :store, :reset_events_cache
-
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
- def reset_events_cache(file)
- model.reset_events_cache if model.is_a?(User)
- end
-
def exists?
model.avatar.file && model.avatar.file.exists?
end
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 5c318cd3b8b..a0bd14df209 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -3,14 +3,13 @@
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
- = cache [event, current_application_settings, "v2.2"] do
- = author_avatar(event, size: 40)
+ = author_avatar(event, size: 40)
- - if event.created_project?
- = render "events/event/created_project", event: event
- - elsif event.push?
- = render "events/event/push", event: event
- - elsif event.commented?
- = render "events/event/note", event: event
- - else
- = render "events/event/common", event: event
+ - if event.created_project?
+ = render "events/event/created_project", event: event
+ - elsif event.push?
+ = render "events/event/push", event: event
+ - elsif event.commented?
+ = render "events/event/note", event: event
+ - else
+ = render "events/event/common", event: event
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 44fff49d99c..64ca3c32e01 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -18,7 +18,7 @@
- few_commits.each do |commit|
= render "events/commit", commit: commit, project: project, event: event
- - create_mr = event.new_ref? && create_mr_button?(project.default_branch, event.ref_name, project)
+ - create_mr = event.new_ref? && create_mr_button?(project.default_branch, event.ref_name, project) && event.authored_by?(current_user)
- if event.commits_count > 1
%li.commits-stat
- if event.commits_count > 2
@@ -35,12 +35,12 @@
Compare #{from_label}...#{truncate_sha(event.commit_to)}
- if create_mr
- %span{"data-user-is" => event.author_id, "data-display" => "inline"}
+ %span
or
= link_to create_mr_path(project.default_branch, event.ref_name, project) do
create a merge request
- elsif create_mr
- %li.commits-stat{"data-user-is" => event.author_id}
+ %li.commits-stat
= link_to create_mr_path(project.default_branch, event.ref_name, project) do
Create Merge Request
- elsif event.rm_ref?
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 757de92d6d4..3e488cf73b9 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -56,5 +56,3 @@
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id')
= render 'layouts/bootlint' if Rails.env.development?
-
- = render 'layouts/user_styles'
diff --git a/app/views/layouts/_user_styles.html.haml b/app/views/layouts/_user_styles.html.haml
deleted file mode 100644
index b76b3cb5510..00000000000
--- a/app/views/layouts/_user_styles.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-:css
- [data-user-is] {
- display: none !important;
- }
-
- [data-user-is="#{current_user.try(:id)}"] {
- display: block !important;
- }
-
- [data-user-is="#{current_user.try(:id)}"][data-display="inline"] {
- display: inline !important;
- }
-
- [data-user-is-not] {
- display: block !important;
- }
-
- [data-user-is-not][data-display="inline"] {
- display: inline !important;
- }
-
- [data-user-is-not="#{current_user.try(:id)}"] {
- display: none !important;
- }
diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index 331727ba9d8..fccddb70d18 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -2,14 +2,33 @@ class AuthorizedProjectsWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ LEASE_TIMEOUT = 1.minute.to_i
+
def self.bulk_perform_async(args_list)
Sidekiq::Client.push_bulk('class' => self, 'args' => args_list)
end
def perform(user_id)
user = User.find_by(id: user_id)
- return unless user
- user.refresh_authorized_projects
+ refresh(user) if user
+ end
+
+ def refresh(user)
+ lease_key = "refresh_authorized_projects:#{user.id}"
+ lease = Gitlab::ExclusiveLease.new(lease_key, timeout: LEASE_TIMEOUT)
+
+ until uuid = lease.try_obtain
+ # Keep trying until we obtain the lease. If we don't do so we may end up
+ # not updating the list of authorized projects properly. To prevent
+ # hammering Redis too much we'll wait for a bit between retries.
+ sleep(1)
+ end
+
+ begin
+ user.refresh_authorized_projects
+ ensure
+ Gitlab::ExclusiveLease.cancel(lease_key, uuid)
+ end
end
end
diff --git a/changelogs/unreleased/events-cache-invalidation.yml b/changelogs/unreleased/events-cache-invalidation.yml
new file mode 100644
index 00000000000..2b30f4dcbce
--- /dev/null
+++ b/changelogs/unreleased/events-cache-invalidation.yml
@@ -0,0 +1,4 @@
+---
+title: Remove caching of events data
+merge_request: 6578
+author:
diff --git a/changelogs/unreleased/refresh-authorizations-with-lease.yml b/changelogs/unreleased/refresh-authorizations-with-lease.yml
new file mode 100644
index 00000000000..bb9b77018e3
--- /dev/null
+++ b/changelogs/unreleased/refresh-authorizations-with-lease.yml
@@ -0,0 +1,4 @@
+---
+title: Use a Redis lease for updating authorized projects
+merge_request: 7733
+author:
diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb
index 18a2df7c059..a984eda5ab5 100644
--- a/db/fixtures/development/04_project.rb
+++ b/db/fixtures/development/04_project.rb
@@ -1,5 +1,4 @@
require 'sidekiq/testing'
-require './db/fixtures/support/serialized_transaction'
Sidekiq::Testing.inline! do
Gitlab::Seeder.quiet do
diff --git a/db/fixtures/development/06_teams.rb b/db/fixtures/development/06_teams.rb
index 04c3690e152..5c2a03fec3f 100644
--- a/db/fixtures/development/06_teams.rb
+++ b/db/fixtures/development/06_teams.rb
@@ -1,5 +1,4 @@
require 'sidekiq/testing'
-require './db/fixtures/support/serialized_transaction'
Sidekiq::Testing.inline! do
Gitlab::Seeder.quiet do
diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb
index 7b3908fae98..916ee8dbac8 100644
--- a/db/fixtures/development/17_cycle_analytics.rb
+++ b/db/fixtures/development/17_cycle_analytics.rb
@@ -1,6 +1,5 @@
require 'sidekiq/testing'
require './spec/support/test_env'
-require './db/fixtures/support/serialized_transaction'
class Gitlab::Seeder::CycleAnalytics
def initialize(project, perf: false)
diff --git a/db/fixtures/support/serialized_transaction.rb b/db/fixtures/support/serialized_transaction.rb
deleted file mode 100644
index d3305b661e5..00000000000
--- a/db/fixtures/support/serialized_transaction.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'gitlab/database'
-
-module Gitlab
- module Database
- def self.serialized_transaction
- connection.transaction { yield }
- end
- end
-end
diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md
index 764c3355714..8e51edd23ef 100644
--- a/doc/development/ux_guide/components.md
+++ b/doc/development/ux_guide/components.md
@@ -43,7 +43,7 @@ Primary links are blue in their rest state. Secondary links (such as the time st
#### Hover
-An underline should always be added on hover. A gray link becomes blue on hover.
+On hover, an underline should be added and the color should change. Both the primary and secondary link should become the darker blue color on hover.
#### Focus
@@ -72,9 +72,7 @@ Secondary buttons are for alternative commands. They should be conveyed by a bu
### Icon and text treatment
Text should be in sentence case, where only the first word is capitalized. "Create issue" is correct, not "Create Issue". Buttons should only contain an icon or a text, not both.
->>>
-TODO: Rationalize this. Ensure that we still believe this.
->>>
+> TODO: Rationalize this. Ensure that we still believe this.
### Colors
Follow the color guidance on the [basics](basics.md#color) page. The default color treatment is the white/grey button.
@@ -85,13 +83,13 @@ Follow the color guidance on the [basics](basics.md#color) page. The default col
Dropdowns are used to allow users to choose one (or many) options from a list of options. If this list of options is more 20, there should generally be a way to search through and filter the options (see the complex filter dropdowns below.)
->>>
-TODO: Will update this section when the new filters UI is implemented.
->>>
+> TODO: Will update this section when the new filters UI is implemented.
![Dropdown states](img/components-dropdown.png)
+### Max size
+The max height for dropdowns should target **10-15 items**. If the height of the dropdown is too large, the list becomes very hard to parse and it is easy to visually lose track of the item you are looking for. Usability also suffers as more mouse movement is required, and you have a larger area in which you hijack the scroll away from the page level. While it may initially seem counterintuitive to not show as many items as you can, it is actually quicker and easier to process the information when it is cropped at a reasonable height.
---
@@ -164,9 +162,7 @@ Cover blocks are generally used to create a heading element for a page, such as
## Panels
->>>
-TODO: Catalog how we are currently using panels and rationalize how they relate to alerts
->>>
+> TODO: Catalog how we are currently using panels and rationalize how they relate to alerts
![Panels](img/components-panels.png)
@@ -174,9 +170,7 @@ TODO: Catalog how we are currently using panels and rationalize how they relate
## Alerts
->>>
-TODO: Catalog how we are currently using alerts
->>>
+> TODO: Catalog how we are currently using alerts
![Alerts](img/components-alerts.png)
diff --git a/doc/development/ux_guide/img/components-anchorlinks.png b/doc/development/ux_guide/img/components-anchorlinks.png
index 7dd6a8a3876..4a9c730566c 100644
--- a/doc/development/ux_guide/img/components-anchorlinks.png
+++ b/doc/development/ux_guide/img/components-anchorlinks.png
Binary files differ
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 2d5c9232425..55b8f888d53 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -35,13 +35,6 @@ module Gitlab
order
end
- def self.serialized_transaction
- opts = {}
- opts[:isolation] = :serializable unless Rails.env.test? && connection.transaction_open?
-
- connection.transaction(opts) { yield }
- end
-
def self.random
Gitlab::Database.postgresql? ? "RANDOM()" : "RAND()"
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index b684053cd02..f8660da031d 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -260,6 +260,24 @@ describe Event, models: true do
end
end
+ describe '#authored_by?' do
+ let(:event) { build(:event) }
+
+ it 'returns true when the event author and user are the same' do
+ expect(event.authored_by?(event.author)).to eq(true)
+ end
+
+ it 'returns false when passing nil as an argument' do
+ expect(event.authored_by?(nil)).to eq(false)
+ end
+
+ it 'returns false when the given user is not the author of the event' do
+ user = double(:user, id: -1)
+
+ expect(event.authored_by?(user)).to eq(false)
+ end
+ end
+
def create_event(project, user, attrs = {})
data = {
before: Gitlab::Git::BLANK_SHA,
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 91826e5884d..14c891994d0 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1349,4 +1349,31 @@ describe User, models: true do
expect(projects).to be_empty
end
end
+
+ describe '#refresh_authorized_projects', redis: true do
+ let(:project1) { create(:empty_project) }
+ let(:project2) { create(:empty_project) }
+ let(:user) { create(:user) }
+
+ before do
+ project1.team << [user, :reporter]
+ project2.team << [user, :guest]
+
+ user.project_authorizations.delete_all
+ user.refresh_authorized_projects
+ end
+
+ it 'refreshes the list of authorized projects' do
+ expect(user.project_authorizations.count).to eq(2)
+ end
+
+ it 'sets the authorized_projects_populated column' do
+ expect(user.authorized_projects_populated).to eq(true)
+ end
+
+ it 'stores the correct access levels' do
+ expect(user.project_authorizations.where(access_level: Gitlab::Access::GUEST).exists?).to eq(true)
+ expect(user.project_authorizations.where(access_level: Gitlab::Access::REPORTER).exists?).to eq(true)
+ end
+ end
end
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index 3fddfb3b62f..8020faa1f9c 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -1,10 +1,6 @@
require 'spec_helper'
describe 'layouts/_head' do
- before do
- stub_template 'layouts/_user_styles.html.haml' => ''
- end
-
it 'escapes HTML-safe strings in page_title' do
stub_helper_with_safe_string(:page_title)
diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb
index 18a1aab766c..95e2458da35 100644
--- a/spec/workers/authorized_projects_worker_spec.rb
+++ b/spec/workers/authorized_projects_worker_spec.rb
@@ -1,22 +1,33 @@
require 'spec_helper'
describe AuthorizedProjectsWorker do
+ let(:worker) { described_class.new }
+
describe '#perform' do
it "refreshes user's authorized projects" do
user = create(:user)
- expect(User).to receive(:find_by).with(id: user.id).and_return(user)
- expect(user).to receive(:refresh_authorized_projects)
+ expect(worker).to receive(:refresh).with(an_instance_of(User))
- described_class.new.perform(user.id)
+ worker.perform(user.id)
end
- context "when user is not found" do
+ context "when the user is not found" do
it "does nothing" do
- expect_any_instance_of(User).not_to receive(:refresh_authorized_projects)
+ expect(worker).not_to receive(:refresh)
- described_class.new.perform(999_999)
+ described_class.new.perform(-1)
end
end
end
+
+ describe '#refresh', redis: true do
+ it 'refreshes the authorized projects of the user' do
+ user = create(:user)
+
+ expect(user).to receive(:refresh_authorized_projects)
+
+ worker.refresh(user)
+ end
+ end
end