diff options
| -rw-r--r-- | CHANGELOG | 5 | ||||
| -rw-r--r-- | Gemfile | 2 | ||||
| -rw-r--r-- | Gemfile.lock | 4 | ||||
| -rw-r--r-- | app/helpers/tree_helper.rb | 2 | ||||
| -rw-r--r-- | app/models/project_services/slack_service.rb | 14 | ||||
| -rw-r--r-- | app/models/user.rb | 5 | ||||
| -rw-r--r-- | doc/api/projects.md | 3 | ||||
| -rw-r--r-- | doc/integration/slack.md | 28 | ||||
| -rw-r--r-- | doc/update/7.3-to-7.4.md | 1 | ||||
| -rw-r--r-- | features/steps/project/services.rb | 4 | ||||
| -rw-r--r-- | lib/api/entities.rb | 6 | ||||
| -rw-r--r-- | lib/gitlab/auth.rb | 2 | ||||
| -rw-r--r-- | lib/gitlab/git.rb | 5 | ||||
| -rw-r--r-- | lib/gitlab/git_access.rb | 4 | ||||
| -rw-r--r-- | spec/lib/gitlab/auth_spec.rb | 10 | ||||
| -rw-r--r-- | spec/lib/gitlab/git_access_spec.rb | 7 | ||||
| -rw-r--r-- | spec/models/slack_message_spec.rb | 2 | ||||
| -rw-r--r-- | spec/models/slack_service_spec.rb | 56 | ||||
| -rw-r--r-- | spec/models/user_spec.rb | 14 | ||||
| -rw-r--r-- | spec/requests/api/projects_spec.rb | 1 | ||||
| -rw-r--r-- | spec/requests/api/session_spec.rb | 26 |
21 files changed, 116 insertions, 85 deletions
diff --git a/CHANGELOG b/CHANGELOG index cc287b67063..ff41575bcc6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,7 +5,10 @@ v 7.5.0 - Fix LDAP config lookup for provider 'ldap' - Add Atlassian Bamboo CI service (Drew Blessing) - Mentioned @user will receive email even if he is not participating in issue or commit + - Session API: Use case-insensitive authentication like in UI (Andrey Krivko) - Tie up loose ends with annotated tags: API & UI (Sean Edge) + - Return valid json for deleting branch via API (sponsored by O'Reilly Media) + - Expose username in project events API (sponsored by O'Reilly Media) v 7.4.2 - Fix internal snippet exposing for unauthenticated users @@ -50,7 +53,7 @@ v 7.4.0 - Fix ambiguous sha problem with mentioned commit - Fixed bug with apostrophe when at mentioning users - Add active directory ldap option - - Developers can push to wiki repo. Protected branches does not affect wiki repo any more + - Developers can push to wiki repo. Protected branches does not affect wiki repo any more - Faster rev list - Fix branch removal @@ -143,7 +143,7 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2" gem "gemnasium-gitlab-service", "~> 0.2" # Slack integration -gem "slack-notifier", "~> 0.3.2" +gem "slack-notifier", "~> 1.0.0" # d3 gem "d3_rails", "~> 3.1.4" diff --git a/Gemfile.lock b/Gemfile.lock index 800f33590cb..c283d4384fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -488,7 +488,7 @@ GEM rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) six (0.2.0) - slack-notifier (0.3.2) + slack-notifier (1.0.0) slim (2.0.2) temple (~> 0.6.6) tilt (>= 1.3.3, < 2.1) @@ -689,7 +689,7 @@ DEPENDENCIES simplecov sinatra six - slack-notifier (~> 0.3.2) + slack-notifier (~> 1.0.0) slim spinach-rails spring (= 1.1.3) diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 9c611a1c147..8e209498323 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -66,7 +66,7 @@ module TreeHelper def tree_breadcrumbs(tree, max_links = 2) if @path.present? part_path = "" - parts = @path.split("\/") + parts = @path.split('/') yield('..', nil) if parts.count > max_links diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 837002ef3c8..963f5440b6f 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -30,24 +30,20 @@ class SlackService < Service def fields [ - { type: 'text', name: 'webhook', placeholder: '' } + { type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' } ] end def execute(push_data) + return unless webhook.present? + message = SlackMessage.new(push_data.merge( project_url: project_url, project_name: project_name )) - credentials = webhook.match(/([\w-]*).slack.com.*services\/(.*)/) - - if credentials.present? - subdomain = credentials[1] - token = credentials[2].split("token=").last - notifier = Slack::Notifier.new(subdomain, token) - notifier.ping(message.pretext, attachments: message.attachments) - end + notifier = Slack::Notifier.new(webhook) + notifier.ping(message.pretext, attachments: message.attachments) end private diff --git a/app/models/user.rb b/app/models/user.rb index 154cc0f3e16..52e63cde6f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -226,6 +226,11 @@ class User < ActiveRecord::Base where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%") end + def by_login(login) + where('lower(username) = :value OR lower(email) = :value', + value: login.to_s.downcase).first + end + def by_username_or_id(name_or_id) where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first end diff --git a/doc/api/projects.md b/doc/api/projects.md index dfe3502b6e4..0055e2e476f 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -186,6 +186,7 @@ Parameters: "target_id": 830, "target_type": "Issue", "author_id": 1, + "author_username": "john", "data": null, "target_title": "Public project search field" }, @@ -196,6 +197,7 @@ Parameters: "target_id": null, "target_type": null, "author_id": 1, + "author_username": "john", "data": { "before": "50d4420237a9de7be1304607147aec22e4a14af7", "after": "c5feabde2d8cd023215af4d2ceeb7a64839fc428", @@ -231,6 +233,7 @@ Parameters: "target_id": 840, "target_type": "Issue", "author_id": 1, + "author_username": "john", "data": null, "target_title": "Finish & merge Code search PR" } diff --git a/doc/integration/slack.md b/doc/integration/slack.md index 95cb0c6fae2..f2e73f272ef 100644 --- a/doc/integration/slack.md +++ b/doc/integration/slack.md @@ -4,15 +4,23 @@ To enable Slack integration you must create an Incoming WebHooks integration on Slack; -1. Sign in to [Slack](https://slack.com) (https://YOURSUBDOMAIN.slack.com/services) -1. Click on the Integrations menu at the top of the page. -1. Add a new Integration. +1. [Sign in to Slack](https://slack.com/signin) + +1. Select **Configure Integrations** from the dropdown next to your team name. + +1. Select the **All Services** tab + +1. Click **Add** next to Incoming Webhooks + 1. Pick Incoming WebHooks -1. Choose the channel name you want to send notifications to, in the Settings section -1. Add Integrations. - - Optional step; You can change bot's name and avatar by clicking "change the name of your bot", and "change the icon" after that you have to click "Save settings". -Now, Slack is ready to get external hooks. Before you leave this page don't forget to get the Token that you'll need on GitLab. You can find it by clicking Expand button, located in the "Instructions for creating Incoming WebHooks" section. It's a random alpha-numeric text 24 characters long. +1. Choose the channel name you want to send notifications to + +1. Click **Add Incoming WebHooks Integration**Add Integrations. + - Optional step; You can change bot's name and avatar by clicking modifying the bot name or avatar under **Integration Settings**. + +1. Copy the **Webhook URL**, we'll need this later for GitLab. + ## On GitLab @@ -26,10 +34,8 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this 1. Fill in your Slack details - - Mark as active it - - Type your subdomain's prefix (If your subdomain is https://somedomain.slack.com you only have to type the somedomain) - - Type in the token you got from Slack - - Type in the channel name you want to use (eg. #announcements) + - Mark it as active + - Paste in the webhook url you got from Slack Have fun :) diff --git a/doc/update/7.3-to-7.4.md b/doc/update/7.3-to-7.4.md index 69d86fb06ed..3f471500c82 100644 --- a/doc/update/7.3-to-7.4.md +++ b/doc/update/7.3-to-7.4.md @@ -9,6 +9,7 @@ ```bash cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` ### 2. Get latest code diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb index 17d62210d10..d5d58070d86 100644 --- a/features/steps/project/services.rb +++ b/features/steps/project/services.rb @@ -109,12 +109,12 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps step 'I fill Slack settings' do check 'Active' - fill_in 'Webhook', with: 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI' + fill_in 'Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' click_button 'Save' end step 'I should see Slack service settings saved' do - find_field('Webhook').value.should == 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI' + find_field('Webhook').value.should == 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' end step 'I click Pushover service link' do diff --git a/lib/api/entities.rb b/lib/api/entities.rb index db2dead487f..40696489ba2 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -184,6 +184,12 @@ module API expose :target_id, :target_type, :author_id expose :data, :target_title expose :created_at + + expose :author_username do |event, options| + if event.author + event.author.username + end + end end class Namespace < Grape::Entity diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index ae33c529b93..30509528b8b 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -1,7 +1,7 @@ module Gitlab class Auth def find(login, password) - user = User.find_by(email: login) || User.find_by(username: login) + user = User.by_login(login) # If no user is found, or it's an LDAP server, try LDAP. # LDAP users are only authenticated via LDAP diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb new file mode 100644 index 00000000000..67aca5e36e9 --- /dev/null +++ b/lib/gitlab/git.rb @@ -0,0 +1,5 @@ +module Gitlab + module Git + BLANK_SHA = '0' * 40 + end +end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index b768a99a0e8..129881060d5 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -67,7 +67,7 @@ module Gitlab if forced_push?(project, oldrev, newrev) :force_push_code_to_protected_branches # and we dont allow remove of protected branch - elsif newrev =~ /0000000/ + elsif newrev == Gitlab::Git::BLANK_SHA :remove_protected_branches else :push_code_to_protected_branches @@ -85,7 +85,7 @@ module Gitlab def forced_push?(project, oldrev, newrev) return false if project.empty_repo? - if oldrev !~ /00000000/ && newrev !~ /00000000/ + if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read missed_refs.split("\n").size > 0 else diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 1f3e1a4a3c1..95fc7e16a11 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -10,13 +10,21 @@ describe Gitlab::Auth do password: password, password_confirmation: password) end - let(:username) { 'john' } + let(:username) { 'John' } # username isn't lowercase, test this let(:password) { 'my-secret' } it "should find user by valid login/password" do expect( gl_auth.find(username, password) ).to eql user end + it 'should find user by valid email/password with case-insensitive email' do + expect(gl_auth.find(user.email.upcase, password)).to eql user + end + + it 'should find user by valid username/password with case-insensitive username' do + expect(gl_auth.find(username.upcase, password)).to eql user + end + it "should not find user with invalid password" do password = 'wrong' expect( gl_auth.find(username, password) ).to_not eql user diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 570b03827a8..fe0a6bbdabb 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -55,12 +55,13 @@ describe Gitlab::GitAccess do def changes { - push_new_branch: '000000000 570e7b2ab refs/heads/wow', + push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow", push_master: '6f6d7e7ed 570e7b2ab refs/heads/master', push_protected_branch: '6f6d7e7ed 570e7b2ab refs/heads/feature', - push_remove_protected_branch: '570e7b2ab 000000000 refs/heads/feature', + push_remove_protected_branch: "570e7b2ab #{Gitlab::Git::BLANK_SHA} "\ + 'refs/heads/feature', push_tag: '6f6d7e7ed 570e7b2ab refs/tags/v1.0.0', - push_new_tag: '000000000 570e7b2ab refs/tags/v7.8.9', + push_new_tag: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/tags/v7.8.9", push_all: ['6f6d7e7ed 570e7b2ab refs/heads/master', '6f6d7e7ed 570e7b2ab refs/heads/feature'] } end diff --git a/spec/models/slack_message_spec.rb b/spec/models/slack_message_spec.rb index 1cd58534702..78d743e01bf 100644 --- a/spec/models/slack_message_spec.rb +++ b/spec/models/slack_message_spec.rb @@ -1,4 +1,4 @@ -require_relative '../../app/models/project_services/slack_message' +require 'spec_helper' describe SlackMessage do subject { SlackMessage.new(args) } diff --git a/spec/models/slack_service_spec.rb b/spec/models/slack_service_spec.rb index 526165e397c..d4840391967 100644 --- a/spec/models/slack_service_spec.rb +++ b/spec/models/slack_service_spec.rb @@ -31,71 +31,27 @@ describe SlackService do end describe "Execute" do - let(:slack) { SlackService.new } - let(:slack_service) { SlackService.new } - let(:user) { create(:user) } + let(:slack) { SlackService.new } + let(:user) { create(:user) } let(:project) { create(:project) } let(:sample_data) { GitPushService.new.sample_data(project, user) } - let(:webhook) { 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI' } - let(:new_webhook) { 'https://hooks.gitlabhq.slack.com/services/cdIj4r4LfXUOySDUjp0tk3OI' } - let(:api_url) { - 'https://gitlabhq.slack.com/services/hooks/incoming-webhook?token=cdIj4r4LfXUOySDUjp0tk3OI' - } + let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } before do slack.stub( project: project, project_id: project.id, service_hook: true, - webhook: webhook + webhook: webhook_url ) - WebMock.stub_request(:post, api_url) + WebMock.stub_request(:post, webhook_url) end it "should call Slack API" do slack.execute(sample_data) - WebMock.should have_requested(:post, api_url).once - end - - context 'with new webhook syntax' do - before do - slack_service.stub( - project: project, - project_id: project.id, - service_hook: true, - webhook: new_webhook - ) - - WebMock.stub_request(:post, api_url) - end - - it "should call Slack API" do - slack_service.execute(sample_data) - - WebMock.should have_requested(:post, api_url).once - end - end - - context 'with new webhook syntax with slack allowed team name' do - before do - @allowed_webhook = 'https://gitlab-hq-123.slack.com/services/hooks/incoming-webhook?token=cdIj4r4LfXUOySDUjp0tk3OI' - slack_service.stub( - project: project, - project_id: project.id, - service_hook: true, - webhook: @allowed_webhook - ) - - WebMock.stub_request(:post, @allowed_webhook) - end - - it "should call Slack API" do - slack_service.execute(sample_data) - - WebMock.should have_requested(:post, @allowed_webhook).once - end + WebMock.should have_requested(:post, webhook_url).once end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6ad57b06e06..6d865cfc691 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -287,6 +287,20 @@ describe User do end end + describe '.by_login' do + let(:username) { 'John' } + let!(:user) { create(:user, username: username) } + + it 'should get the correct user' do + expect(User.by_login(user.email.upcase)).to eq user + expect(User.by_login(user.email)).to eq user + expect(User.by_login(username.downcase)).to eq user + expect(User.by_login(username)).to eq user + expect(User.by_login(nil)).to be_nil + expect(User.by_login('')).to be_nil + end + end + describe 'all_ssh_keys' do it { should have_many(:keys).dependent(:destroy) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index ba7ec7b2be9..cb7a2705573 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -339,6 +339,7 @@ describe API::API, api: true do json_event['action_name'].should == 'joined' json_event['project_id'].to_i.should == project.id + json_event['author_username'].should == user.username end it "should return a 404 error if not found" do diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb index 013f425d6ce..57b2e6cbd6a 100644 --- a/spec/requests/api/session_spec.rb +++ b/spec/requests/api/session_spec.rb @@ -19,6 +19,32 @@ describe API::API, api: true do end end + context 'when email has case-typo and password is valid' do + it 'should return private token' do + post api('/session'), email: user.email.upcase, password: '12345678' + expect(response.status).to eq 201 + + expect(json_response['email']).to eq user.email + expect(json_response['private_token']).to eq user.private_token + expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['can_create_project']).to eq user.can_create_project? + expect(json_response['can_create_group']).to eq user.can_create_group? + end + end + + context 'when login has case-typo and password is valid' do + it 'should return private token' do + post api('/session'), login: user.username.upcase, password: '12345678' + expect(response.status).to eq 201 + + expect(json_response['email']).to eq user.email + expect(json_response['private_token']).to eq user.private_token + expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['can_create_project']).to eq user.can_create_project? + expect(json_response['can_create_group']).to eq user.can_create_group? + end + end + context "when invalid password" do it "should return authentication error" do post api("/session"), email: user.email, password: '123' |
