Commit 43a3a401 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into mention-all

parents 396c5c97 e3befaed
Please view this file on the master branch, on stable branches it's out of date.
v 8.4.0 (unreleased)
- Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu)
- Implement new UI for group page
- Implement search inside emoji picker
- Add project permissions to all project API endpoints (Stan Hu)
- Only allow group/project members to mention `@all`
- Expose Git's version in the admin area
- Add "Frequently used" category to emoji picker
- Add CAS support (tduehr)
- Add link to merge request on build detail page.
v 8.3.1 (unreleased)
v 8.3.1
- Fix Error 500 when global milestones have slashes (Stan Hu)
- Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu)
- Fix LDAP identity and user retrieval when special characters are used
- Move Sidekiq-cron configuration to gitlab.yml
v 8.3.0
- Add CAS support (tduehr)
- Bump rack-attack to 4.3.1 for security fix (Stan Hu)
- API support for starred projects for authorized user (Zeger-Jan van de Weg)
- Add link to merge request on build detail page.
- Add open_issues_count to project API (Stan Hu)
- Expand character set of usernames created by Omniauth (Corey Hinshaw)
- Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
......@@ -74,7 +78,6 @@ v 8.3.0
- Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present
- Persist runners registration token in database
- Fix online editor should not remove newlines at the end of the file
- Expose Git's version in the admin area
v 8.2.3
- Fix application settings cache not expiring after changes (Stan Hu)
......
......@@ -10,6 +10,7 @@ class @AwardsHandler
if $(".emoji-menu").is(":visible")
$(".emoji-menu").hide()
@renderFrequentlyUsedBlock()
@setupSearch()
addAward: (emoji) ->
......@@ -20,6 +21,8 @@ class @AwardsHandler
$(".emoji-menu").hide()
addAwardToEmojiBar: (emoji) ->
@addEmojiToFrequentlyUsedList(emoji)
emoji = @normilizeEmojiName(emoji)
if @exist(emoji)
if @isActive(emoji)
......@@ -117,6 +120,29 @@ class @AwardsHandler
normilizeEmojiName: (emoji) ->
@aliases[emoji] || emoji
addEmojiToFrequentlyUsedList: (emoji) ->
frequently_used_emojis = @getFrequentlyUsedEmojis()
frequently_used_emojis.push(emoji)
$.cookie('frequently_used_emojis', frequently_used_emojis.join(","), { expires: 365 })
getFrequentlyUsedEmojis: ->
frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",")
frequently_used_emojis = ["thumbsup", "thumbsdown"].concat(frequently_used_emojis)
_.compact(_.uniq(frequently_used_emojis))
renderFrequentlyUsedBlock: ->
frequently_used_emojis = @getFrequentlyUsedEmojis()
ul = $("<ul>")
for emoji in frequently_used_emojis
do (emoji) ->
$(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul)
$("input.emoji-search").after(ul).after($("<h5>").text("Frequently used"))
setupSearch: ->
$("input.emoji-search").keyup (ev) =>
term = $(ev.target).val()
......@@ -125,7 +151,7 @@ class @AwardsHandler
$("ul.emoji-search,h5.emoji-search").remove()
if term
# Generate search result block
# Generate a search result block
h5 = $("<h5>").text("Search results").addClass("emoji-search")
found_emojis = @searchEmojis(term).show()
ul = $("<ul>").addClass("emoji-search").append(found_emojis)
......
class @Project
constructor: ->
# Git protocol switcher
$('.js-protocol-switch').click ->
$('ul.clone-options-dropdown a').click ->
return if $(@).hasClass('active')
......@@ -10,7 +10,8 @@ class @Project
# Add the active class for the clicked button
$(@).toggleClass('active')
url = $(@).data('clone')
url = $("#project_clone").val()
console.log("url",url)
# Update the input field
$('#project_clone').val(url)
......
class @Star
constructor: ->
$('.project-home-panel .toggle-star').on('ajax:success', (e, data, status, xhr) ->
$this = $(this)
$starSpan = $this.find('span')
$starIcon = $this.find('i')
toggleStar = (isStarred) ->
$this.parent().find('span.count').text data.star_count
if isStarred
$starSpan.removeClass('starred').text 'Star'
$starIcon.removeClass('fa-star').addClass 'fa-star-o'
else
$starSpan.addClass('starred').text 'Unstar'
$starIcon.removeClass('fa-star-o').addClass 'fa-star'
return
toggleStar $starSpan.hasClass('starred')
return
).on 'ajax:error', (e, xhr, status, error) ->
new Flash('Star toggle failed. Try again later.', 'alert')
return
\ No newline at end of file
......@@ -91,21 +91,83 @@
}
}
.input-group {
.git-clone-holder {
display: inline-table;
position: relative;
top: 17px;
}
.project-repo-buttons {
margin-top: 12px;
margin-bottom: 0px;
.count-buttons {
display: block;
margin-bottom: 12px;
}
.btn {
@include btn-gray;
text-transform: none;
}
.count-with-arrow {
display: inline-block;
position: relative;
margin-left: 4px;
.arrow {
&:before {
content: '';
display: inline-block;
position: absolute;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
top: 50%;
left: 0;
margin-top: -6px;
border-width: 7px 5px 7px 0;
border-right-color: #dce0e5;
}
&:after {
content: '';
position: absolute;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
top: 50%;
left: 1px;
margin-top: -9px;
border-width: 10px 7px 10px 0;
border-right-color: #FFF;
}
}
.count {
@include btn-gray;
display: inline-block;
background: white;
border-radius: 2px;
border-width: 1px;
border-style: solid;
font-size: 13px;
font-weight: 600;
line-height: 20px;
padding: 11px 16px;
letter-spacing: .4px;
padding: 10px;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
white-space: nowrap;
margin: 0 11px 0px 4px;
&:hover {
background: #FFF;
}
}
}
}
......@@ -125,6 +187,13 @@
margin-right: 45px;
}
.clone-options {
display: table-cell;
a.btn {
width: 100%;
}
}
.form-control {
cursor: auto;
@extend .monospace;
......
......@@ -171,7 +171,7 @@ class ProjectsController < ApplicationController
@project.reload
render json: {
html: view_to_html_string("projects/buttons/_star")
star_count: @project.star_count
}
end
......
......@@ -132,14 +132,14 @@ class Ability
end
def public_project_rules
project_guest_rules + [
@public_project_rules ||= project_guest_rules + [
:download_code,
:fork_project
]
end
def project_guest_rules
[
@project_guest_rules ||= [
:read_project,
:read_wiki,
:read_issue,
......@@ -157,7 +157,7 @@ class Ability
end
def project_report_rules
project_guest_rules + [
@project_report_rules ||= project_guest_rules + [
:create_commit_status,
:read_commit_statuses,
:download_code,
......@@ -170,7 +170,7 @@ class Ability
end
def project_dev_rules
project_report_rules + [
@project_dev_rules ||= project_report_rules + [
:admin_merge_request,
:create_merge_request,
:create_wiki,
......@@ -181,7 +181,7 @@ class Ability
end
def project_archived_rules
[
@project_archived_rules ||= [
:create_merge_request,
:push_code,
:push_code_to_protected_branches,
......@@ -191,7 +191,7 @@ class Ability
end
def project_master_rules
project_dev_rules + [
@project_master_rules ||= project_dev_rules + [
:push_code_to_protected_branches,
:update_project_snippet,
:update_merge_request,
......@@ -206,7 +206,7 @@ class Ability
end
def project_admin_rules
project_master_rules + [
@project_admin_rules ||= project_master_rules + [
:change_namespace,
:change_visibility_level,
:rename_project,
......@@ -332,7 +332,7 @@ class Ability
end
if snippet.public? || snippet.internal?
rules << :read_personal_snippet
rules << :read_personal_snippet
end
rules
......
......@@ -12,6 +12,7 @@
class Identity < ActiveRecord::Base
include Sortable
include CaseSensitivity
belongs_to :user
validates :provider, presence: true
......
......@@ -6,7 +6,7 @@
- else
= render 'explore/head'
.gray-content-block.clearfix
.gray-content-block.clearfix.second-block
= render 'filter'
= render 'projects', projects: @projects
= paginate @projects, theme: "gitlab"
......@@ -7,7 +7,7 @@
= render 'explore/head'
.explore-trending-block
.gray-content-block
.gray-content-block.second-block
.pull-right
= render 'explore/projects/dropdown'
.oneline
......
......@@ -7,7 +7,7 @@
= render 'explore/head'
.explore-trending-block
.gray-content-block
.gray-content-block.second-block
.pull-right
= render 'explore/projects/dropdown'
.oneline
......
......@@ -27,7 +27,7 @@
= icon('rss')
.project-repo-buttons
.split-one
.split-one.count-buttons
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
......@@ -38,3 +38,6 @@
= render 'projects/buttons/dropdown'
= render 'projects/buttons/notifications'
:coffeescript
new Star()
\ No newline at end of file
......@@ -4,10 +4,15 @@
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do
= icon('code-fork fw')
Fork
%div.count-with-arrow
%span.arrow
%span.count
= @project.forks_count
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do
= icon('code-fork fw')
Fork
%div.count-with-arrow
%span.arrow
%span.count
= @project.forks_count
- if current_user
= link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do
= icon('star fw')
%span.count
- if current_user.starred?(@project)
= icon('star fw')
%span.starred Unstar
- else
= icon('star-o fw')
%span Star
%div.count-with-arrow
%span.arrow
%span.count.star-count
= @project.star_count
:javascript
$('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) {
$(this).replaceWith(data.html);
})
.on('ajax:error', function (e, xhr, status, error) {
new Flash('Star toggle failed. Try again later.', 'alert');
});
- else
= link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do
= icon('star fw')
Star
%div.count-with-arrow
%span.arrow
%span.count
= @project.star_count
- project = project || @project
.git-clone-holder.input-group
.input-group-addon.git-protocols
.input-group-btn
= ssh_clone_button(project)
.input-group-btn
= http_clone_button(project)
.git-clone-holder
.btn-group.clone-options
%a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
%span
= default_clone_protocol.upcase
= icon('angle-down')
%ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
%li
%a#ssh-selector{href: @project.ssh_url_to_repo}
SSH
%li
%a#http-selector{href: @project.http_url_to_repo}
HTTPS
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
.input-group-btn
= clipboard_button(clipboard_target: '#project_clone')
:javascript
$('ul.clone-options-dropdown a').on('click',function(e){
e.preventDefault();
var $this = $(this);
$('a.clone-dropdown-btn span').text($this.text());
$('#project_clone').val($this.attr('href'));
});
@project-create
Feature: Project Create
In order to get access to project sections
A user with ability to create a project
......
......@@ -26,5 +26,5 @@ Feature: Award Emoji
@javascript
Scenario: I add award emoji using regular comment
Given I leave comment with a single emoji
Then I have award added
Given I leave comment with a single emoji
Then I have award added
@project-stars
Feature: Project Star
Scenario: New projects have 0 stars
Given public project "Community"
......
......@@ -26,7 +26,8 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
end
step 'I click on HTTP' do
click_button 'HTTP'
find('#clone-dropdown').click
find('#http-selector').click
end
step 'Remote url should update to http link' do
......@@ -34,7 +35,8 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
end
step 'If I click on SSH' do
click_button 'SSH'
find('#clone-dropdown').click
find('#ssh-selector').click
end
step 'Remote url should update to ssh link' do
......
......@@ -32,6 +32,6 @@ class Spinach::Features::ProjectStar < Spinach::FeatureSteps
protected
def has_n_stars(n)
expect(page).to have_css(".star-btn .count", text: n, visible: true)
expect(page).to have_css(".star-count", text: n, visible: true)
end
end
......@@ -14,7 +14,7 @@ module Gitlab
# LDAP distinguished name is case-insensitive
identity = ::Identity.
where(provider: provider).
where('lower(extern_uid) = ?', uid.mb_chars.downcase.to_s).last
iwhere(extern_uid: uid).last
identity && identity.user
end
end
......@@ -31,7 +31,7 @@ module Gitlab
def find_by_uid_and_provider
self.class.find_by_uid_and_provider(
auth_hash.uid.downcase, auth_hash.provider)
auth_hash.uid, auth_hash.provider)
end
def find_by_email
......@@ -47,7 +47,7 @@ module Gitlab
# 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.
......
......@@ -64,7 +64,7 @@ module Gitlab
# If a corresponding person exists with same uid in a LDAP server,
# set up a Gitlab user with dual LDAP and Omniauth identities.
if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn.downcase, ldap_person.provider)
if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn, ldap_person.provider)
# Case when a LDAP user already exists in Gitlab. Add the Omniauth identity to existing account.
user.identities.build(extern_uid: auth_hash.uid, provider: auth_hash.provider)
else
......
#= require jquery.ui.all
#= require jquery-ui
#= require new_branch_form
describe 'Branch', ->
......
......@@ -42,6 +42,21 @@ describe Gitlab::LDAP::User, lib: true do
end
end
describe '.find_by_uid_and_provider' do
it 'retrieves the correct user' do
special_info = {
name: 'John Åström',
email: 'john@example.com',
nickname: 'jastrom'
}
special_hash = OmniAuth::AuthHash.new(uid: 'CN=John Åström,CN=Users,DC=Example,DC=com', provider: 'ldapmain', info: special_info)
special_chars_user = described_class.new(special_hash)
user = special_chars_user.save
expect(described_class.find_by_uid_and_provider(special_hash.uid, special_hash.provider)).to eq user
end
end
describe :find_or_create do
it "finds the user if already existing" do
create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment