summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/syntax_highlight.coffee9
-rw-r--r--app/assets/stylesheets/generic/common.scss4
-rw-r--r--app/assets/stylesheets/highlight/dark.scss6
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss6
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss5
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss5
-rw-r--r--app/assets/stylesheets/highlight/white.scss5
-rw-r--r--app/controllers/application_controller.rb9
-rw-r--r--app/controllers/users_controller.rb4
-rw-r--r--app/helpers/gitlab_markdown_helper.rb2
-rw-r--r--app/helpers/preferences_helper.rb27
-rw-r--r--app/models/user.rb6
-rw-r--r--app/services/notification_service.rb11
-rw-r--r--app/views/profiles/preferences/show.html.haml8
-rw-r--r--app/views/profiles/show.html.haml5
-rw-r--r--app/views/search/results/_blob.html.haml2
-rw-r--r--app/views/search/results/_snippet_blob.html.haml2
-rw-r--r--app/views/search/results/_wiki_blob.html.haml2
-rw-r--r--app/views/shared/_file_highlight.html.haml2
-rw-r--r--db/migrate/20150817163600_deduplicate_user_identities.rb14
-rw-r--r--doc/workflow/importing/import_projects_from_github.md2
-rw-r--r--features/user.feature5
-rw-r--r--lib/gitlab/color_schemes.rb67
-rw-r--r--lib/gitlab/current_settings.rb2
-rw-r--r--lib/gitlab/ldap/user.rb11
-rw-r--r--lib/gitlab/themes.rb18
-rw-r--r--lib/redcarpet/render/gitlab_html.rb5
-rw-r--r--spec/features/markdown_spec.rb8
-rw-r--r--spec/helpers/events_helper_spec.rb5
-rw-r--r--spec/helpers/preferences_helper_spec.rb92
-rw-r--r--spec/lib/gitlab/color_schemes_spec.rb45
-rw-r--r--spec/lib/gitlab/ldap/user_spec.rb22
-rw-r--r--spec/lib/gitlab/themes_spec.rb3
-rw-r--r--spec/services/notification_service_spec.rb11
37 files changed, 311 insertions, 129 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 386ce7ca6d4..d7d1eb7ab41 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.0.0 (unreleased)
+ - Upgrade gitlab_git to 7.2.15 to fix `git blame` errors with ISO-encoded files (Stan Hu)
- Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu)
- Improve dropdown positioning on the project home page (Hannes Rosenögger)
- Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu)
@@ -22,6 +23,9 @@ v 8.0.0 (unreleased)
- Fix 500 error when submit project snippet without body
- Improve search page usability
- Bring more UI consistency in way how projects, snippets and groups lists are rendered
+ - Make all profiles public
+ - Fixed login failure when extern_uid changes (Joel Koglin)
+ - Don't notify users without access to the project when they are (accidentally) mentioned in a note.
v 7.14.1
- Improve abuse reports management from admin area
diff --git a/Gemfile b/Gemfile
index 1e0f387d03a..2a55bb31cb9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -38,7 +38,7 @@ gem "browser", '~> 1.0.0'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
-gem "gitlab_git", '~> 7.2.14'
+gem "gitlab_git", '~> 7.2.15'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
diff --git a/Gemfile.lock b/Gemfile.lock
index bedcf9c85b0..d09bc53e379 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -274,7 +274,7 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.1.0)
gemojione (~> 2.0)
- gitlab_git (7.2.14)
+ gitlab_git (7.2.15)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0)
@@ -787,7 +787,7 @@ DEPENDENCIES
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-linguist (~> 3.0.1)
gitlab_emoji (~> 0.1)
- gitlab_git (~> 7.2.14)
+ gitlab_git (~> 7.2.15)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.1)
gollum-lib (~> 4.0.2)
diff --git a/app/assets/javascripts/syntax_highlight.coffee b/app/assets/javascripts/syntax_highlight.coffee
new file mode 100644
index 00000000000..510f15d1b49
--- /dev/null
+++ b/app/assets/javascripts/syntax_highlight.coffee
@@ -0,0 +1,9 @@
+# Applies a syntax highlighting color scheme CSS class to any element with the
+# `js-syntax-highlight` class
+#
+# ### Example Markup
+#
+# <div class="js-syntax-highlight"></div>
+#
+$(document).on 'ready page:load', ->
+ $('.js-syntax-highlight').addClass(gon.user_color_scheme)
diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss
index 2674fde41ae..e5902597c4d 100644
--- a/app/assets/stylesheets/generic/common.scss
+++ b/app/assets/stylesheets/generic/common.scss
@@ -132,10 +132,6 @@ p.time {
text-shadow: none;
}
-.highlight_word {
- background: #fafe3d;
-}
-
.thin_area{
height: 150px;
}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index c8cb18ec35f..8323a8598ec 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -21,6 +21,12 @@ pre.code.highlight.dark,
background-color: #557 !important;
}
+ // Search result highlight
+ span.highlight_word {
+ background: #ffe792;
+ color: #000000;
+ }
+
.hll { background-color: #373b41 }
.c { color: #969896 } /* Comment */
.err { color: #cc6666 } /* Error */
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 001e8b31020..e8381674336 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -21,6 +21,12 @@ pre.code.monokai,
background-color: #49483e !important;
}
+ // Search result highlight
+ span.highlight_word {
+ background: #ffe792;
+ color: #000000;
+ }
+
.hll { background-color: #49483e }
.c { color: #75715e } /* Comment */
.err { color: #960050; background-color: #1e0010 } /* Error */
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index f5b827e7c02..bd41480aefb 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -21,6 +21,11 @@ pre.code.highlight.solarized-dark,
background-color: #174652 !important;
}
+ // Search result highlight
+ span.highlight_word {
+ background: #094554;
+ }
+
/* Solarized Dark
For use with Jekyll and Pygments
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
index 6b44c00c305..4cc62863870 100644
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -21,6 +21,11 @@ pre.code.highlight.solarized-light,
background-color: #ddd8c5 !important;
}
+ // Search result highlight
+ span.highlight_word {
+ background: #eee8d5;
+ }
+
/* Solarized Light
For use with Jekyll and Pygments
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index a52ffc971d1..e0edfb80b42 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -21,6 +21,11 @@ pre.code.highlight.white,
background-color: #f8eec7 !important;
}
+ // Search result highlight
+ span.highlight_word {
+ background: #fafe3d;
+ }
+
.hll { background-color: #f8f8f8 }
.c { color: #999988; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index ef1170e16da..cb1cf13d34d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -192,11 +192,12 @@ class ApplicationController < ActionController::Base
end
def add_gon_variables
+ gon.api_version = API::API.version
+ gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
gon.default_issues_tracker = Project.new.default_issue_tracker.to_param
- gon.api_version = API::API.version
- gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
- gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
- gon.max_file_size = current_application_settings.max_attachment_size;
+ gon.max_file_size = current_application_settings.max_attachment_size
+ gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
+ gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
if current_user
gon.current_user_id = current_user.id
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 2bb5c338cf6..1484356a7f4 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -51,10 +51,6 @@ class UsersController < ApplicationController
def set_user
@user = User.find_by_username!(params[:username])
-
- unless current_user || @user.public_profile?
- return authenticate_user!
- end
end
def authorized_projects_ids
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index eb3f72a307d..114730eb948 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -58,7 +58,7 @@ module GitlabMarkdownHelper
@options = options
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
- rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, options)
+ rend = Redcarpet::Render::GitlabHTML.new(self, options)
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
@markdown = Redcarpet::Markdown.new(rend, MARKDOWN_OPTIONS)
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index ea774e28ecf..7f1b6a69926 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -1,25 +1,5 @@
# Helper methods for per-User preferences
module PreferencesHelper
- COLOR_SCHEMES = {
- 1 => 'white',
- 2 => 'dark',
- 3 => 'solarized-light',
- 4 => 'solarized-dark',
- 5 => 'monokai',
- }
- COLOR_SCHEMES.default = 'white'
-
- # Helper method to access the COLOR_SCHEMES
- #
- # The keys are the `color_scheme_ids`
- # The values are the `name` of the scheme.
- #
- # The preview images are `name-scheme-preview.png`
- # The stylesheets should use the css class `.name`
- def color_schemes
- COLOR_SCHEMES.freeze
- end
-
# Maps `dashboard` values to more user-friendly option text
DASHBOARD_CHOICES = {
projects: 'Your Projects (default)',
@@ -50,12 +30,11 @@ module PreferencesHelper
end
def user_application_theme
- theme = Gitlab::Themes.by_id(current_user.try(:theme_id))
- theme.css_class
+ Gitlab::Themes.for_user(current_user).css_class
end
- def user_color_scheme_class
- COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
+ def user_color_scheme
+ Gitlab::ColorSchemes.for_user(current_user).css_class
end
def prefer_readme?
diff --git a/app/models/user.rb b/app/models/user.rb
index f70761074c5..48e0e6ed48b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -104,7 +104,7 @@ class User < ActiveRecord::Base
# Profile
has_many :keys, dependent: :destroy
has_many :emails, dependent: :destroy
- has_many :identities, dependent: :destroy
+ has_many :identities, dependent: :destroy, autosave: true
# Groups
has_many :members, dependent: :destroy
@@ -637,10 +637,6 @@ class User < ActiveRecord::Base
email.start_with?('temp-email-for-oauth')
end
- def public_profile?
- authorized_projects.public_only.any?
- end
-
def avatar_url(size = nil)
if avatar.present?
[gitlab_config.url, avatar.url].join
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 3735a136365..e294b23bc23 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -107,12 +107,17 @@ class NotificationService
recipients = []
+ mentioned_users = note.mentioned_users
+ mentioned_users.select! do |user|
+ user.can?(:read_project, note.project)
+ end
+
# Add all users participating in the thread (author, assignee, comment authors)
participants =
if target.respond_to?(:participants)
target.participants(note.author)
else
- note.mentioned_users
+ mentioned_users
end
recipients = recipients.concat(participants)
@@ -120,8 +125,8 @@ class NotificationService
recipients = add_project_watchers(recipients, note.project)
# Reject users with Mention notification level, except those mentioned in _this_ note.
- recipients = reject_mention_users(recipients - note.mentioned_users, note.project)
- recipients = recipients + note.mentioned_users
+ recipients = reject_mention_users(recipients - mentioned_users, note.project)
+ recipients = recipients + mentioned_users
recipients = reject_muted_users(recipients, note.project)
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 1134317ee06..aa0361a0a1b 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -22,11 +22,11 @@
.panel-heading
Syntax highlighting theme
.panel-body
- - color_schemes.each do |color_scheme_id, color_scheme|
+ - Gitlab::ColorSchemes.each do |scheme|
= label_tag do
- .preview= image_tag "#{color_scheme}-scheme-preview.png"
- = f.radio_button :color_scheme_id, color_scheme_id
- = color_scheme.tr('-_', ' ').titleize
+ .preview= image_tag "#{scheme.css_class}-scheme-preview.png"
+ = f.radio_button :color_scheme_id, scheme.id
+ = scheme.name
.panel.panel-default
.panel-heading
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 9fdeddfcc7a..c519e52e596 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -100,11 +100,6 @@
%hr
= link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
- - if @user.public_profile?
- .alert.alert-info
- %h4 Public profile
- %p Your profile is publicly visible because you joined public project(s)
-
.row
.col-md-7
diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml
index 58f58eff54d..0fe8a3b490a 100644
--- a/app/views/search/results/_blob.html.haml
+++ b/app/views/search/results/_blob.html.haml
@@ -7,4 +7,4 @@
%strong
= blob.filename
.file-content.code.term
- = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, user_color_scheme_class: 'white'
+ = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline
diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml
index 95099853918..9a4f9fb9485 100644
--- a/app/views/search/results/_snippet_blob.html.haml
+++ b/app/views/search/results/_snippet_blob.html.haml
@@ -23,7 +23,7 @@
.nothing-here-block Empty file
- else
.file-content.code
- %div.highlighted-data{class: user_color_scheme_class}
+ %div.highlighted-data{ class: user_color_scheme }
.line-numbers
- snippet_blob[:snippet_chunks].each do |snippet|
- unless snippet[:data].empty?
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index c03438eb952..f5859481d46 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -7,4 +7,4 @@
%strong
= wiki_blob.filename
.file-content.code.term
- = render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline, user_color_scheme_class: 'white'
+ = render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index d6a2e177da1..57c3aff3e18 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,4 +1,4 @@
-.file-content.code{class: user_color_scheme_class}
+.file-content.code.js-syntax-highlight{ class: user_color_scheme }
.line-numbers
- if blob.data.present?
- blob.data.lines.each_index do |index|
diff --git a/db/migrate/20150817163600_deduplicate_user_identities.rb b/db/migrate/20150817163600_deduplicate_user_identities.rb
new file mode 100644
index 00000000000..fab669c2905
--- /dev/null
+++ b/db/migrate/20150817163600_deduplicate_user_identities.rb
@@ -0,0 +1,14 @@
+class DeduplicateUserIdentities < ActiveRecord::Migration
+ def change
+ execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
+ execute 'CREATE TEMPORARY TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;'
+ execute 'DELETE FROM identities WHERE id NOT IN ( SELECT MIN(id) FROM tt_migration_DeduplicateUserIdentities GROUP BY user_id, provider);'
+ execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
+ end
+
+ def down
+ # This is an irreversible migration;
+ # If someone is trying to rollback for other reasons, we should not throw an Exception.
+ # raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md
index 3efa92cb868..2d77c6d1172 100644
--- a/doc/workflow/importing/import_projects_from_github.md
+++ b/doc/workflow/importing/import_projects_from_github.md
@@ -17,4 +17,4 @@ If you want to import from a GitHub Enterprise instance, you need to use GitLab
* To import a project, you can simple click "Add". The importer will import your repository and issues. Once the importer is done, a new GitLab project will be created with your imported data.
### Note
-When you import your projects from GitHub, it is not possible to keep your labels and milestones and issue numbers won't match. We are working on improving this in the near future.
+When you import your projects from GitHub, it is not possible to keep your labels and milestones. We are working on improving this in the near future.
diff --git a/features/user.feature b/features/user.feature
index 69618e929c4..35eae842e77 100644
--- a/features/user.feature
+++ b/features/user.feature
@@ -14,11 +14,6 @@ Feature: User
And I should not see project "Internal"
And I should see project "Community"
- Scenario: I visit user "John Doe" page while not signed in when he is not authorized to a public project
- Given "John Doe" owns internal project "Internal"
- When I visit user "John Doe" page
- Then I should be redirected to sign in page
-
# Signed in as someone else
Scenario: I visit user "John Doe" page while signed in as someone else when he owns a public project
diff --git a/lib/gitlab/color_schemes.rb b/lib/gitlab/color_schemes.rb
new file mode 100644
index 00000000000..9c4664df903
--- /dev/null
+++ b/lib/gitlab/color_schemes.rb
@@ -0,0 +1,67 @@
+module Gitlab
+ # Module containing GitLab's syntax color scheme definitions and helper
+ # methods for accessing them.
+ module ColorSchemes
+ # Struct class representing a single Scheme
+ Scheme = Struct.new(:id, :name, :css_class)
+
+ SCHEMES = [
+ Scheme.new(1, 'White', 'white'),
+ Scheme.new(2, 'Dark', 'dark'),
+ Scheme.new(3, 'Solarized Light', 'solarized-light'),
+ Scheme.new(4, 'Solarized Dark', 'solarized-dark'),
+ Scheme.new(5, 'Monokai', 'monokai')
+ ].freeze
+
+ # Convenience method to get a space-separated String of all the color scheme
+ # classes that might be applied to a code block.
+ #
+ # Returns a String
+ def self.body_classes
+ SCHEMES.collect(&:css_class).uniq.join(' ')
+ end
+
+ # Get a Scheme by its ID
+ #
+ # If the ID is invalid, returns the default Scheme.
+ #
+ # id - Integer ID
+ #
+ # Returns a Scheme
+ def self.by_id(id)
+ SCHEMES.detect { |s| s.id == id } || default
+ end
+
+ # Returns the number of defined Schemes
+ def self.count
+ SCHEMES.size
+ end
+
+ # Get the default Scheme
+ #
+ # Returns a Scheme
+ def self.default
+ by_id(1)
+ end
+
+ # Iterate through each Scheme
+ #
+ # Yields the Scheme object
+ def self.each(&block)
+ SCHEMES.each(&block)
+ end
+
+ # Get the Scheme for the specified user, or the default
+ #
+ # user - User record
+ #
+ # Returns a Scheme
+ def self.for_user(user)
+ if user
+ by_id(user.color_scheme_id)
+ else
+ default
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 1a2a50a14d0..7ad3ed8728f 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -4,7 +4,7 @@ module Gitlab
key = :current_application_settings
RequestStore.store[key] ||= begin
- if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
+ if ActiveRecord::Base.connection.active? && ActiveRecord::Base.connection.table_exists?('application_settings')
ApplicationSetting.current || ApplicationSetting.create_from_defaults
else
fake_application_settings
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index f7f3ba9ad7d..04a22237478 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -44,9 +44,14 @@ module Gitlab
gl_user.skip_reconfirmation!
gl_user.email = auth_hash.email
- # Build new identity only if we dont have have same one
- gl_user.identities.find_or_initialize_by(provider: auth_hash.provider,
- extern_uid: auth_hash.uid)
+ # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved.
+ identity = gl_user.identities.find { |identity| identity.provider == auth_hash.provider }
+ identity ||= gl_user.identities.build(provider: auth_hash.provider)
+
+ # For a new user set extern_uid to the LDAP DN
+ # For an existing user with matching email but changed DN, update the DN.
+ # For an existing user with no change in DN, this line changes nothing.
+ identity.extern_uid = auth_hash.uid
gl_user
end
diff --git a/lib/gitlab/themes.rb b/lib/gitlab/themes.rb
index 5209df92795..83f91de810c 100644
--- a/lib/gitlab/themes.rb
+++ b/lib/gitlab/themes.rb
@@ -37,6 +37,11 @@ module Gitlab
THEMES.detect { |t| t.id == id } || default
end
+ # Returns the number of defined Themes
+ def self.count
+ THEMES.size
+ end
+
# Get the default Theme
#
# Returns a Theme
@@ -51,6 +56,19 @@ module Gitlab
THEMES.each(&block)
end
+ # Get the Theme for the specified user, or the default
+ #
+ # user - User record
+ #
+ # Returns a Theme
+ def self.for_user(user)
+ if user
+ by_id(user.theme_id)
+ else
+ default
+ end
+ end
+
private
def self.default_id
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index f57b56cbdf0..9cb8e91d6e3 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -4,9 +4,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
attr_reader :template
alias_method :h, :template
- def initialize(template, color_scheme, options = {})
+ def initialize(template, options = {})
@template = template
- @color_scheme = color_scheme
@options = options.dup
@options.reverse_merge!(
@@ -35,7 +34,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
end
formatter = Rouge::Formatters::HTMLGitlab.new(
- cssclass: "code highlight #{@color_scheme} #{lexer.tag}"
+ cssclass: "code highlight js-syntax-highlight #{lexer.tag}"
)
formatter.format(lexer.lex(code))
end
diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb
index 3da4dfc2b23..4fe019f8342 100644
--- a/spec/features/markdown_spec.rb
+++ b/spec/features/markdown_spec.rb
@@ -64,8 +64,8 @@ describe 'GitLab Markdown', feature: true do
it 'parses fenced code blocks' do
aggregate_failures do
- expect(doc).to have_selector('pre.code.highlight.white.c')
- expect(doc).to have_selector('pre.code.highlight.white.python')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.c')
+ expect(doc).to have_selector('pre.code.highlight.js-syntax-highlight.python')
end
end
@@ -224,8 +224,4 @@ describe 'GitLab Markdown', feature: true do
def current_user
@feat.user
end
-
- def user_color_scheme_class
- :white
- end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index da58ab98462..e68a5ec29ab 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -28,8 +28,7 @@ describe EventsHelper do
it 'should display the first line of a code block' do
input = "```\nCode block\nwith two lines\n```"
- expected = '<pre class="code highlight white plaintext"><code>' \
- 'Code block...</code></pre>'
+ expected = %r{<pre.+><code>Code block\.\.\.</code></pre>}
expect(event_note(input)).to match(expected)
end
@@ -55,7 +54,7 @@ describe EventsHelper do
it 'should preserve code color scheme' do
input = "```ruby\ndef test\n 'hello world'\nend\n```"
- expected = '<pre class="code highlight white ruby">' \
+ expected = '<pre class="code highlight js-syntax-highlight ruby">' \
"<code><span class=\"k\">def</span> <span class=\"nf\">test</span>\n" \
" <span class=\"s1\">\'hello world\'</span>\n" \
"<span class=\"k\">end</span>" \
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index d814b562113..06f69262b71 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -1,72 +1,82 @@
require 'spec_helper'
describe PreferencesHelper do
+ describe 'dashboard_choices' do
+ it 'raises an exception when defined choices may be missing' do
+ expect(User).to receive(:dashboards).and_return(foo: 'foo')
+ expect { helper.dashboard_choices }.to raise_error(RuntimeError)
+ end
+
+ it 'raises an exception when defined choices may be using the wrong key' do
+ expect(User).to receive(:dashboards).and_return(foo: 'foo', bar: 'bar')
+ expect { helper.dashboard_choices }.to raise_error(KeyError)
+ end
+
+ it 'provides better option descriptions' do
+ expect(helper.dashboard_choices).to match_array [
+ ['Your Projects (default)', 'projects'],
+ ['Starred Projects', 'stars']
+ ]
+ end
+ end
+
describe 'user_application_theme' do
context 'with a user' do
it "returns user's theme's css_class" do
- user = double('user', theme_id: 3)
- allow(self).to receive(:current_user).and_return(user)
- expect(user_application_theme).to eq 'ui_green'
+ stub_user(theme_id: 3)
+
+ expect(helper.user_application_theme).to eq 'ui_green'
end
it 'returns the default when id is invalid' do
- user = double('user', theme_id: Gitlab::Themes::THEMES.size + 5)
+ stub_user(theme_id: Gitlab::Themes.count + 5)
allow(Gitlab.config.gitlab).to receive(:default_theme).and_return(2)
- allow(self).to receive(:current_user).and_return(user)
- expect(user_application_theme).to eq 'ui_charcoal'
+ expect(helper.user_application_theme).to eq 'ui_charcoal'
end
end
context 'without a user' do
- before do
- allow(self).to receive(:current_user).and_return(nil)
- end
-
it 'returns the default theme' do
- expect(user_application_theme).to eq Gitlab::Themes.default.css_class
+ stub_user
+
+ expect(helper.user_application_theme).to eq Gitlab::Themes.default.css_class
end
end
end
- describe 'dashboard_choices' do
- it 'raises an exception when defined choices may be missing' do
- expect(User).to receive(:dashboards).and_return(foo: 'foo')
- expect { dashboard_choices }.to raise_error(RuntimeError)
- end
+ describe 'user_color_scheme' do
+ context 'with a user' do
+ it "returns user's scheme's css_class" do
+ allow(helper).to receive(:current_user).
+ and_return(double(color_scheme_id: 3))
- it 'raises an exception when defined choices may be using the wrong key' do
- expect(User).to receive(:dashboards).and_return(foo: 'foo', bar: 'bar')
- expect { dashboard_choices }.to raise_error(KeyError)
- end
+ expect(helper.user_color_scheme).to eq 'solarized-light'
+ end
- it 'provides better option descriptions' do
- expect(dashboard_choices).to match_array [
- ['Your Projects (default)', 'projects'],
- ['Starred Projects', 'stars']
- ]
+ it 'returns the default when id is invalid' do
+ allow(helper).to receive(:current_user).
+ and_return(double(color_scheme_id: Gitlab::ColorSchemes.count + 5))
+ end
end
- end
- describe 'user_color_scheme_class' do
- context 'with current_user is nil' do
- it 'should return a string' do
- allow(self).to receive(:current_user).and_return(nil)
- expect(user_color_scheme_class).to be_kind_of(String)
+ context 'without a user' do
+ it 'returns the default theme' do
+ stub_user
+
+ expect(helper.user_color_scheme).
+ to eq Gitlab::ColorSchemes.default.css_class
end
end
+ end
- context 'with a current_user' do
- (1..5).each do |color_scheme_id|
- context "with color_scheme_id == #{color_scheme_id}" do
- it 'should return a string' do
- current_user = double(color_scheme_id: color_scheme_id)
- allow(self).to receive(:current_user).and_return(current_user)
- expect(user_color_scheme_class).to be_kind_of(String)
- end
- end
- end
+ def stub_user(messages = {})
+ if messages.empty?
+ allow(helper).to receive(:current_user).and_return(nil)
+ else
+ allow(helper).to receive(:current_user).
+ and_return(double('user', messages))
end
end
end
diff --git a/spec/lib/gitlab/color_schemes_spec.rb b/spec/lib/gitlab/color_schemes_spec.rb
new file mode 100644
index 00000000000..c7be45dbcd3
--- /dev/null
+++ b/spec/lib/gitlab/color_schemes_spec.rb
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe Gitlab::ColorSchemes do
+ describe '.body_classes' do
+ it 'returns a space-separated list of class names' do
+ css = described_class.body_classes
+
+ expect(css).to include('white')
+ expect(css).to include(' solarized-light ')
+ expect(css).to include(' monokai')
+ end
+ end
+
+ describe '.by_id' do
+ it 'returns a scheme by its ID' do
+ expect(described_class.by_id(1).name).to eq 'White'
+ expect(described_class.by_id(4).name).to eq 'Solarized Dark'
+ end
+ end
+
+ describe '.default' do
+ it 'returns the default scheme' do
+ expect(described_class.default.id).to eq 1
+ end
+ end
+
+ describe '.each' do
+ it 'passes the block to the SCHEMES Array' do
+ ids = []
+ described_class.each { |scheme| ids << scheme.id }
+ expect(ids).not_to be_empty
+ end
+ end
+
+ describe '.for_user' do
+ it 'returns default when user is nil' do
+ expect(described_class.for_user(nil).id).to eq 1
+ end
+
+ it "returns user's preferred color scheme" do
+ user = double(color_scheme_id: 5)
+ expect(described_class.for_user(user).id).to eq 5
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb
index 7cfca96f4e0..84d9fb54b61 100644
--- a/spec/lib/gitlab/ldap/user_spec.rb
+++ b/spec/lib/gitlab/ldap/user_spec.rb
@@ -47,6 +47,28 @@ describe Gitlab::LDAP::User do
expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
end
+ it 'connects to existing ldap user if the extern_uid changes' do
+ existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'old-uid', provider: 'ldapmain')
+ expect{ ldap_user.save }.not_to change{ User.count }
+
+ existing_user.reload
+ expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
+ expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
+ expect(existing_user.id).to eql ldap_user.gl_user.id
+ end
+
+ it 'maintains an identity per provider' do
+ existing_user = create(:omniauth_user, email: 'john@example.com', provider: 'twitter')
+ expect(existing_user.identities.count).to eql(1)
+
+ ldap_user.save
+ expect(ldap_user.gl_user.identities.count).to eql(2)
+
+ # Expect that find_by provider only returns a single instance of an identity and not an Enumerable
+ expect(ldap_user.gl_user.identities.find_by(provider: 'twitter')).to be_instance_of Identity
+ expect(ldap_user.gl_user.identities.find_by(provider: auth_hash.provider)).to be_instance_of Identity
+ end
+
it "creates a new user if not found" do
expect{ ldap_user.save }.to change{ User.count }.by(1)
end
diff --git a/spec/lib/gitlab/themes_spec.rb b/spec/lib/gitlab/themes_spec.rb
index 9c6c3fd8104..e554458e41c 100644
--- a/spec/lib/gitlab/themes_spec.rb
+++ b/spec/lib/gitlab/themes_spec.rb
@@ -43,9 +43,6 @@ describe Gitlab::Themes do
ids = []
described_class.each { |theme| ids << theme.id }
expect(ids).not_to be_empty
-
- # TODO (rspeicher): RSpec 3.x
- # expect(described_class.each).to yield_with_arg(described_class::Theme)
end
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 9da6c9dc949..8865335d0d1 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -31,13 +31,16 @@ describe NotificationService do
describe 'Notes' do
context 'issue note' do
- let(:project) { create(:empty_project, :public) }
+ let(:project) { create(:empty_project, :private) }
let(:issue) { create(:issue, project: project, assignee: create(:user)) }
let(:mentioned_issue) { create(:issue, assignee: issue.assignee) }
- let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@mention referenced') }
+ let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@mention referenced, @outsider also') }
before do
build_team(note.project)
+ project.team << [issue.author, :master]
+ project.team << [issue.assignee, :master]
+ project.team << [note.author, :master]
end
describe :new_note do
@@ -53,6 +56,7 @@ describe NotificationService do
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
should_not_email(@unsubscriber.id)
+ should_not_email(@u_outsider_mentioned)
notification.new_note(note)
end
@@ -444,12 +448,15 @@ describe NotificationService do
@u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION)
@u_committer = create(:user, username: 'committer')
@u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING)
+ @u_outsider_mentioned = create(:user, username: 'outsider')
project.team << [@u_watcher, :master]
project.team << [@u_participating, :master]
+ project.team << [@u_participant_mentioned, :master]
project.team << [@u_disabled, :master]
project.team << [@u_mentioned, :master]
project.team << [@u_committer, :master]
+ project.team << [@u_not_mentioned, :master]
end
def add_users_with_subscription(project, issuable)