diff options
94 files changed, 811 insertions, 339 deletions
diff --git a/CHANGELOG b/CHANGELOG index 2e0d86862bf..4d8fb3585e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -50,6 +50,11 @@ v 7.8.0 (unreleased) - Prevent losing unsaved comments by automatically restoring them when comment page is loaded again. - Don't allow page to be scaled on mobile. - Clean the username acquired from OAuth/LDAP so it doesn't fail username validation and block signing up. + - Show assignees in merge request index page (Kelvin Mutuma) + - Link head panel titles to relevant root page. + - Allow users that signed up via OAuth to set their password in order to use Git over HTTP(S). + - Show users button to share their newly created public or internal projects on twitter + - Add quick help links to the GitLab pricing and feature comparison pages. v 7.7.2 - Update GitLab Shell to version 2.4.2 that fixes a bug when developers can push to protected branch @@ -85,9 +90,9 @@ v 7.7.0 - When accept merge request - do merge using sidaekiq job - Enable web signups by default - Fixes for diff comments: drag-n-drop images, selecting images - - Fixes for edit comments: drag-n-drop images, preview mode, selecting images, save & update + - Fixes for edit comments: drag-n-drop images, preview mode, selecting images, save & update - Remove password strength indicator - + v 7.6.0 diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 5a9cc66c8f0..eb8c1fa1426 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -16,5 +16,11 @@ class @Project $('.hide-no-ssh-message').on 'click', (e) -> path = '/' $.cookie('hide_no_ssh_message', 'false', { path: path }) - $(@).parents('.no-ssh-key-message').hide() + $(@).parents('.no-ssh-key-message').remove() + e.preventDefault() + + $('.hide-no-password-message').on 'click', (e) -> + path = '/' + $.cookie('hide_no_password_message', 'false', { path: path }) + $(@).parents('.no-password-message').remove() e.preventDefault() diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss index 9582c995980..b7614513216 100644 --- a/app/assets/stylesheets/sections/events.scss +++ b/app/assets/stylesheets/sections/events.scss @@ -64,6 +64,10 @@ .md { font-size: 13px; + + iframe.twitter-share-button { + vertical-align: bottom; + } } pre { diff --git a/app/assets/stylesheets/sections/login.scss b/app/assets/stylesheets/sections/login.scss index 3a3644c12b7..d366300511e 100644 --- a/app/assets/stylesheets/sections/login.scss +++ b/app/assets/stylesheets/sections/login.scss @@ -40,8 +40,7 @@ .login-heading h3 { font-weight: 300; line-height: 1.5; - margin: 0; - display: none; + margin: 0 0 10px 0; } .login-footer { diff --git a/app/assets/stylesheets/sections/nav_sidebar.scss b/app/assets/stylesheets/sections/nav_sidebar.scss index b35043821da..9c7d1a03a03 100644 --- a/app/assets/stylesheets/sections/nav_sidebar.scss +++ b/app/assets/stylesheets/sections/nav_sidebar.scss @@ -126,7 +126,7 @@ .nav-sidebar { margin-top: 20px; - position: absolute; + position: fixed; top: 45px; width: 52px; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 7458542fc73..2b0c500e97a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -26,6 +26,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :signup_enabled, :signin_enabled, :gravatar_enabled, + :twitter_sharing_enabled, :sign_in_text, :home_page_url ) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 232f30b759d..ecedb31a7f8 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -121,7 +121,7 @@ class Admin::UsersController < Admin::ApplicationController params.require(:user).permit( :email, :remember_me, :bio, :name, :username, :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password, - :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, + :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :hide_no_password, :projects_limit, :can_create_group, :admin, :key_id ) end diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 1191ce47eba..0c614969a3f 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -11,7 +11,7 @@ class Profiles::PasswordsController < ApplicationController end def create - unless @user.valid_password?(user_params[:current_password]) + unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password]) redirect_to new_profile_password_path, alert: 'You must provide a valid current password' return end @@ -21,7 +21,8 @@ class Profiles::PasswordsController < ApplicationController result = @user.update_attributes( password: new_password, - password_confirmation: new_password_confirmation + password_confirmation: new_password_confirmation, + password_automatically_set: false ) if result @@ -39,8 +40,9 @@ class Profiles::PasswordsController < ApplicationController password_attributes = user_params.select do |key, value| %w(password password_confirmation).include?(key.to_s) end + password_attributes[:password_automatically_set] = false - unless @user.valid_password?(user_params[:current_password]) + unless @user.password_automatically_set || @user.valid_password?(user_params[:current_password]) redirect_to edit_profile_password_path, alert: 'You must provide a valid current password' return end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index c0b7e2223a2..f7584c03411 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -67,7 +67,7 @@ class ProfilesController < ApplicationController params.require(:user).permit( :email, :password, :password_confirmation, :bio, :name, :username, :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, - :avatar, :hide_no_ssh_key, + :avatar, :hide_no_ssh_key, :hide_no_password ) end end diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index b3110eacc18..2b3e70f7bdb 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -29,7 +29,7 @@ class Projects::ServicesController < Projects::ApplicationController if @service.execute(data) message = { notice: 'We sent a request to the provided URL' } else - message = { alert: 'We tried to send a request to the provided URL but error occured' } + message = { alert: 'We tried to send a request to the provided URL but an error occured' } end redirect_to :back, message diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 64b820160d3..22eb8f67f9a 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -27,7 +27,7 @@ class Projects::TagsController < Projects::ApplicationController tag = @repository.find_tag(params[:id]) if tag && @repository.rm_tag(tag.name) - Event.create_ref_event(@project, current_user, tag, 'rm', 'refs/tags') + EventCreateService.new.push_ref(@project, current_user, tag, 'rm', 'refs/tags') end respond_to do |format| diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 1ed3bc388fb..6ac048e4b83 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -106,6 +106,7 @@ class SnippetsController < ApplicationController def set_title @title = 'Snippets' + @title_url = snippets_path end def snippet_params diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 57d8ef09faf..84a04c5ebe6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -19,6 +19,7 @@ class UsersController < ApplicationController where(project_id: authorized_projects_ids).limit(30) @title = @user.name + @title_url = user_path(@user) respond_to do |format| format.html diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 04299316102..1ee086da997 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -3,6 +3,10 @@ module ApplicationSettingsHelper current_application_settings.gravatar_enabled? end + def twitter_sharing_enabled? + current_application_settings.twitter_sharing_enabled? + end + def signup_enabled? current_application_settings.signup_enabled? end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index d05f6df5f9f..ca64499675c 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -10,11 +10,15 @@ module EventsHelper end def event_action_name(event) - target = if event.target_type - event.target_type.titleize.downcase - else - 'project' - end + target = if event.target_type + if event.note? + event.note_target_type + else + event.target_type.titleize.downcase + end + else + 'project' + end [event.action_name, target].join(" ") end @@ -42,21 +46,30 @@ module EventsHelper end def event_feed_title(event) - if event.issue? - "#{event.author_name} #{event.action_name} issue ##{event.target_iid}: #{event.issue_title} at #{event.project_name}" - elsif event.merge_request? - "#{event.author_name} #{event.action_name} MR ##{event.target_iid}: #{event.merge_request_title} at #{event.project_name}" - elsif event.push? - "#{event.author_name} #{event.push_action_name} #{event.ref_type} #{event.ref_name} at #{event.project_name}" - elsif event.membership_changed? - "#{event.author_name} #{event.action_name} #{event.project_name}" - elsif event.note? && event.note_commit? - "#{event.author_name} commented on #{event.note_target_type} #{event.note_short_commit_id} at #{event.project_name}" - elsif event.note? - "#{event.author_name} commented on #{event.note_target_type} ##{truncate event.note_target_iid} at #{event.project_name}" - else - "" + words = [] + words << event.author_name + words << event_action_name(event) + + if event.push? + words << event.ref_type + words << event.ref_name + words << "at" + elsif event.commented? + if event.note_commit? + words << event.note_short_commit_id + else + words << "##{truncate event.note_target_iid}" + end + words << "at" + elsif event.target + words << "##{event.target_iid}:" + words << event.target.title if event.target.respond_to?(:title) + words << "at" end + + words << event.project_name + + words.join(" ") end def event_feed_url(event) @@ -96,8 +109,6 @@ module EventsHelper render "events/event_push", event: event elsif event.merge_request? render "events/event_merge_request", merge_request: event.merge_request - elsif event.push? - render "events/event_push", event: event elsif event.note? render "events/event_note", note: event.note end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6d4e220b16c..f1d918e5457 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -8,6 +8,7 @@ # signup_enabled :boolean # signin_enabled :boolean # gravatar_enabled :boolean +# twitter_sharing_enabled :boolean # sign_in_text :text # created_at :datetime # updated_at :datetime @@ -30,6 +31,7 @@ class ApplicationSetting < ActiveRecord::Base default_branch_protection: Settings.gitlab['default_branch_protection'], signup_enabled: Settings.gitlab['signup_enabled'], signin_enabled: Settings.gitlab['signin_enabled'], + twitter_sharing_enabled: Settings.gitlab['twitter_sharing_enabled'], gravatar_enabled: Settings.gravatar['enabled'], sign_in_text: Settings.extra['sign_in_text'], ) diff --git a/app/models/event.rb b/app/models/event.rb index 9a42d380f87..cae7f0be85b 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -49,29 +49,6 @@ class Event < ActiveRecord::Base scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent } class << self - def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads') - commit = project.repository.commit(ref.target) - - if action.to_s == 'add' - before = '00000000' - after = commit.id - else - before = commit.id - after = '00000000' - end - - Event.create( - project: project, - action: Event::PUSHED, - data: { - ref: "#{prefix}/#{ref.name}", - before: before, - after: after - }, - author_id: user.id - ) - end - def reset_event_cache_for(target) Event.where(target_id: target.id, target_type: target.class.to_s). order('id DESC').limit(100). @@ -84,6 +61,8 @@ class Event < ActiveRecord::Base true elsif membership_changed? true + elsif created_project? + true else (issue? || merge_request? || note? || milestone?) && target end @@ -98,25 +77,51 @@ class Event < ActiveRecord::Base end def target_title - if target && target.respond_to?(:title) - target.title - end + target.title if target && target.respond_to?(:title) + end + + def created? + action == CREATED end def push? - action == self.class::PUSHED && valid_push? + action == PUSHED && valid_push? end def merged? - action == self.class::MERGED + action == MERGED end def closed? - action == self.class::CLOSED + action == CLOSED end def reopened? - action == self.class::REOPENED + action == REOPENED + end + + def joined? + action == JOINED + end + + def left? + action == LEFT + end + + def commented? + action == COMMENTED + end + + def membership_changed? + joined? || left? + end + + def created_project? + created? && !target + end + + def created_target? + created? && target end def milestone? @@ -135,32 +140,32 @@ class Event < ActiveRecord::Base target_type == "MergeRequest" end - def joined? - action == JOINED - end - - def left? - action == LEFT - end - - def membership_changed? - joined? || left? + def milestone + target if milestone? end def issue - target if target_type == "Issue" + target if issue? end def merge_request - target if target_type == "MergeRequest" + target if merge_request? end def note - target if target_type == "Note" + target if note? end def action_name - if closed? + if push? + if new_ref? + "pushed new" + elsif rm_ref? + "deleted" + else + "pushed to" + end + elsif closed? "closed" elsif merged? "accepted" @@ -168,6 +173,10 @@ class Event < ActiveRecord::Base 'joined' elsif left? 'left' + elsif commented? + "commented on" + elsif created_project? + "created" else "opened" end @@ -236,16 +245,6 @@ class Event < ActiveRecord::Base tag? ? "tag" : "branch" end - def push_action_name - if new_ref? - "pushed new" - elsif rm_ref? - "deleted" - else - "pushed to" - end - end - def push_with_commits? md_ref? && commits.any? && commit_from && commit_to end diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 30c09f768d7..e4791d0f0aa 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -114,13 +114,11 @@ class ProjectMember < Member end def post_create_hook - Event.create( - project_id: self.project.id, - action: Event::JOINED, - author_id: self.user.id - ) - - notification_service.new_team_member(self) unless owner? + unless owner? + event_service.join_project(self.project, self.user) + notification_service.new_team_member(self) + end + system_hook_service.execute_hooks_for(self, :create) end @@ -129,15 +127,14 @@ class ProjectMember < Member end def post_destroy_hook - Event.create( - project_id: self.project.id, - action: Event::LEFT, - author_id: self.user.id - ) - + event_service.leave_project(self.project, self.user) system_hook_service.execute_hooks_for(self, :destroy) end + def event_service + EventCreateService.new + end + def notification_service NotificationService.new end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index ba0b2b71cf9..2c7ed376265 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -44,6 +44,10 @@ class Namespace < ActiveRecord::Base scope :root, -> { where('type IS NULL') } + def self.by_path(path) + where('lower(path) = :value', value: path.downcase).first + end + def self.search(query) where("name LIKE :query OR path LIKE :query", query: "%#{query}%") end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 51b2fb3dcc7..c991a34ecdb 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -65,6 +65,29 @@ class IssueTrackerService < Service end end + def execute(data) + message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." + result = false + + begin + url = URI.parse(self.project_url) + + if url.host && url.port + http = Net::HTTP.start(url.host, url.port, { open_timeout: 5, read_timeout: 5 }) + response = http.head("/") + + if response + message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}" + result = true + end + end + rescue Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => error + message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}" + end + Rails.logger.info(message) + result + end + private def enabled_in_gitlab_config diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index a159c287485..4c056605ea8 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -14,9 +14,23 @@ # class JiraService < IssueTrackerService + include Rails.application.routes.url_helpers prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + def help + issue_tracker_link = help_page_path("integration", "external-issue-tracker") + + line1 = "Setting `project_url`, `issues_url` and `new_issue_url` will "\ + "allow a user to easily navigate to the Jira issue tracker. "\ + "See the [integration doc](#{issue_tracker_link}) for details." + + line2 = 'Support for referencing commits and automatic closing of Jira issues directly ' \ + 'from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html)' + + [line1, line2].join("\n\n") + end + def title if self.properties && self.properties['title'].present? self.properties['title'] diff --git a/app/models/user.rb b/app/models/user.rb index 278f5c662df..d4018f0c897 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,6 +40,7 @@ # confirmation_sent_at :datetime # unconfirmed_email :string(255) # hide_no_ssh_key :boolean default(FALSE) +# hide_no_password :boolean default(FALSE) # website_url :string(255) default(""), not null # last_credential_check_at :datetime # github_access_token :string(255) @@ -60,6 +61,7 @@ class User < ActiveRecord::Base default_value_for :can_create_group, gitlab_config.default_can_create_group default_value_for :can_create_team, false default_value_for :hide_no_ssh_key, false + default_value_for :hide_no_password, false default_value_for :projects_limit, current_application_settings.default_projects_limit default_value_for :theme_id, gitlab_config.default_theme @@ -252,7 +254,7 @@ class User < ActiveRecord::Base counter = 0 base = username - while by_login(username).present? + while User.by_login(username).present? || Namespace.by_path(username).present? counter += 1 username = "#{base}#{counter}" end @@ -290,7 +292,8 @@ class User < ActiveRecord::Base def namespace_uniq namespace_name = self.username - if Namespace.find_by(path: namespace_name) + existing_namespace = Namespace.by_path(namespace_name) + if existing_namespace && existing_namespace != self.namespace self.errors.add :username, "already exists" end end diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index 901f67bafb3..5e971c7891c 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -17,7 +17,7 @@ class CreateBranchService < BaseService new_branch = repository.find_branch(branch_name) if new_branch - Event.create_ref_event(project, current_user, new_branch, 'add') + EventCreateService.new.push_ref(project, current_user, new_branch, 'add') return success(new_branch) else return error('Invalid reference name') diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb index 041c2287c36..a735d3f7f20 100644 --- a/app/services/create_tag_service.rb +++ b/app/services/create_tag_service.rb @@ -26,7 +26,7 @@ class CreateTagService < BaseService project.gitlab_ci_service.async_execute(push_data) end - Event.create_ref_event(project, current_user, new_tag, 'add', 'refs/tags') + EventCreateService.new.push_ref(project, current_user, new_tag, 'add', 'refs/tags') success(new_tag) else error('Invalid reference name') diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb index cae6327fe72..c26aee2b0aa 100644 --- a/app/services/delete_branch_service.rb +++ b/app/services/delete_branch_service.rb @@ -25,7 +25,7 @@ class DeleteBranchService < BaseService end if repository.rm_branch(branch_name) - Event.create_ref_event(project, current_user, branch, 'rm') + EventCreateService.new.push_ref(project, current_user, branch, 'rm') success('Branch was removed') else return error('Failed to remove branch') diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb index 8d8a5873e62..ba9547b9242 100644 --- a/app/services/event_create_service.rb +++ b/app/services/event_create_service.rb @@ -7,58 +7,98 @@ # class EventCreateService def open_issue(issue, current_user) - create_event(issue, current_user, Event::CREATED) + create_record_event(issue, current_user, Event::CREATED) end def close_issue(issue, current_user) - create_event(issue, current_user, Event::CLOSED) + create_record_event(issue, current_user, Event::CLOSED) end def reopen_issue(issue, current_user) - create_event(issue, current_user, Event::REOPENED) + create_record_event(issue, current_user, Event::REOPENED) end def open_mr(merge_request, current_user) - create_event(merge_request, current_user, Event::CREATED) + create_record_event(merge_request, current_user, Event::CREATED) end def close_mr(merge_request, current_user) - create_event(merge_request, current_user, Event::CLOSED) + create_record_event(merge_request, current_user, Event::CLOSED) end def reopen_mr(merge_request, current_user) - create_event(merge_request, current_user, Event::REOPENED) + create_record_event(merge_request, current_user, Event::REOPENED) end def merge_mr(merge_request, current_user) - create_event(merge_request, current_user, Event::MERGED) + create_record_event(merge_request, current_user, Event::MERGED) end def open_milestone(milestone, current_user) - create_event(milestone, current_user, Event::CREATED) + create_record_event(milestone, current_user, Event::CREATED) end def close_milestone(milestone, current_user) - create_event(milestone, current_user, Event::CLOSED) + create_record_event(milestone, current_user, Event::CLOSED) end def reopen_milestone(milestone, current_user) - create_event(milestone, current_user, Event::REOPENED) + create_record_event(milestone, current_user, Event::REOPENED) end def leave_note(note, current_user) - create_event(note, current_user, Event::COMMENTED) + create_record_event(note, current_user, Event::COMMENTED) + end + + def join_project(project, current_user) + create_event(project, current_user, Event::JOINED) + end + + def leave_project(project, current_user) + create_event(project, current_user, Event::LEFT) + end + + def create_project(project, current_user) + create_event(project, current_user, Event::CREATED) + end + + def push_ref(project, current_user, ref, action = 'add', prefix = 'refs/heads') + commit = project.repository.commit(ref.target) + + if action.to_s == 'add' + before = '00000000' + after = commit.id + else + before = commit.id + after = '00000000' + end + + data = { + ref: "#{prefix}/#{ref.name}", + before: before, + after: after + } + + push(project, current_user, data) + end + + def push(project, current_user, push_data) + create_event(project, current_user, Event::PUSHED, data: push_data) end private - def create_event(record, current_user, status) - Event.create( - project: record.project, - target_id: record.id, - target_type: record.class.name, + def create_record_event(record, current_user, status) + create_event(record.project, current_user, status, target_id: record.id, target_type: record.class.name) + end + + def create_event(project, current_user, status, attributes = {}) + attributes.reverse_merge!( + project: project, action: status, author_id: current_user.id ) + + Event.create(attributes) end end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index c775f79ec29..f21e6ac207d 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -52,7 +52,7 @@ class GitPushService end @push_data = post_receive_data(oldrev, newrev, ref) - create_push_event(@push_data) + EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup) end @@ -60,15 +60,6 @@ class GitPushService protected - def create_push_event(push_data) - Event.create!( - project: project, - action: Event::PUSHED, - data: push_data, - author_id: push_data[:user_id] - ) - end - # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. def process_commit_messages(ref) diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index c24809ad607..46d8987f12d 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -5,7 +5,7 @@ class GitTagPushService @project, @user = project, user @push_data = create_push_data(oldrev, newrev, ref) - create_push_event + EventCreateService.new.push(project, user, @push_data) project.repository.expire_cache project.execute_hooks(@push_data.dup, :tag_push_hooks) @@ -22,13 +22,4 @@ class GitTagPushService Gitlab::PushDataBuilder. build(project, user, oldrev, newrev, ref, []) end - - def create_push_event - Event.create!( - project: project, - action: Event::PUSHED, - data: push_data, - author_id: push_data[:user_id] - ) - end end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 139de70114b..4fe790b98f1 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -52,13 +52,7 @@ module Projects end end - if @project.persisted? - if @project.wiki_enabled? - @project.create_wiki - end - - after_create_actions - end + after_create_actions if @project.persisted? @project rescue => ex @@ -79,6 +73,10 @@ module Projects def after_create_actions log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"") + + @project.create_wiki if @project.wiki_enabled? + + event_service.create_project(@project, current_user) system_hook_service.execute_hooks_for(@project, :create) unless @project.group diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index ae0c70a79c7..f528d69f431 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -19,6 +19,11 @@ = f.label :gravatar_enabled, class: 'control-label' .col-sm-10 = f.check_box :gravatar_enabled, class: 'checkbox' + .form-group + = f.label :twitter_sharing_enabled, "Twitter enabled", class: 'control-label' + .col-sm-10 + = f.check_box :twitter_sharing_enabled, class: 'checkbox' + %span.help-block Show users button to share their newly created public or internal projects on twitter %fieldset %legend Misc .form-group diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml index d8242e37621..5df8849317b 100644 --- a/app/views/admin/services/_form.html.haml +++ b/app/views/admin/services/_form.html.haml @@ -9,6 +9,10 @@ .alert.alert-danger - @service.errors.full_messages.each do |msg| %p= msg + - if @service.help.present? + .bs-callout + = preserve do + = markdown @service.help - @service.fields.each do |field| - name = field[:name] diff --git a/app/views/dashboard/_zero_authorized_projects.html.haml b/app/views/dashboard/_zero_authorized_projects.html.haml index f78ce69ef9e..6e76f95b34e 100644 --- a/app/views/dashboard/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/_zero_authorized_projects.html.haml @@ -17,7 +17,8 @@ - if current_user.can_create_project? .link_holder = link_to new_project_path, class: "btn btn-new" do - New project » + %i.fa.fa-plus + New Project - if current_user.can_create_group? %hr @@ -31,7 +32,8 @@ Groups are the best way to manage projects and members. .link_holder = link_to new_group_path, class: "btn btn-new" do - New group » + %i.fa.fa-plus + New Group -if @publicish_project_count > 0 %hr @@ -47,4 +49,4 @@ Public projects are an easy way to allow everyone to have read-only access. .link_holder = link_to trending_explore_projects_path, class: "btn btn-new" do - Browse public projects » + Browse public projects diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml index dba3025b3cc..21e44fb1c60 100644 --- a/app/views/dashboard/projects.html.haml +++ b/app/views/dashboard/projects.html.haml @@ -1,6 +1,10 @@ %h3.page-title My Projects + = link_to new_project_path, class: "btn btn-new pull-right" do + %i.fa.fa-plus + New Project + %p.light All projects you have access to are listed here. Public projects are not included here unless you are a member %hr diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index c07e409d583..d3e37f7494c 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -1,7 +1,3 @@ = render 'devise/shared/signup_box' -.clearfix.prepend-top-20 - = render 'devise/shared/sign_in_link' - %p - %span.light Did not receive confirmation email? - = link_to "Send again", new_confirmation_path(resource_name)
\ No newline at end of file += render 'devise/shared/sign_in_link'
\ No newline at end of file diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 6d8415613d1..fa2460518fc 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,15 +1,6 @@ %div = render 'devise/shared/signin_box' - - if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable? - .prepend-top-20 - = render 'devise/shared/oauth_box' - - if signup_enabled? .prepend-top-20 = render 'devise/shared/signup_box' - -.clearfix.prepend-top-20 - %p - %span.light Did not receive confirmation email? - = link_to "Send again", new_confirmation_path(resource_name) diff --git a/app/views/devise/shared/_oauth_box.html.haml b/app/views/devise/shared/_oauth_box.html.haml deleted file mode 100644 index c2e1373de30..00000000000 --- a/app/views/devise/shared/_oauth_box.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- providers = additional_providers -- if providers.present? - .login-box{:'data-no-turbolink' => 'data-no-turbolink'} - %span Sign in with - - providers.each do |provider| - %span - - if default_providers.include?(provider) - = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) - - else - = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn" diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index 70587329033..805cf816231 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -1,6 +1,10 @@ .login-box - .login-heading - %h3 Sign in + - if signup_enabled? + .login-heading + %h3 Existing user? Sign in + - else + .login-heading + %h3 Sign in .login-body - if ldap_enabled? %ul.nav.nav-tabs @@ -23,3 +27,16 @@ - else %div No authentication methods configured. + +- if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable? + .clearfix.prepend-top-20 + %p + %span.light + Sign in with + - providers = additional_providers + - providers.each do |provider| + %span.light + - if default_providers.include?(provider) + = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) + - else + = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
\ No newline at end of file diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 8a6dc19ab64..dcf60c90430 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -1,6 +1,10 @@ .login-box - .login-heading - %h3 Sign up + - if signin_enabled? + .login-heading + %h3 New user? Create an account + - else + .login-heading + %h3 Create an account .login-body = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| .devise-errors @@ -15,3 +19,8 @@ = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true %div = f.submit "Sign up", class: "btn-create btn" + +.clearfix.prepend-top-20 + %p + %span.light Did not receive confirmation email? + = link_to "Send again", new_confirmation_path(resource_name)
\ No newline at end of file diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index c7976ba564f..02b1dec753c 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -3,12 +3,14 @@ .event-item-timestamp #{time_ago_with_tooltip(event.created_at)} - = cache event do + = cache [event, current_user] do = image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:'' - if event.push? = render "events/event/push", event: event - - elsif event.note? + - elsif event.commented? = render "events/event/note", event: event + - elsif event.created_project? + = render "events/event/created_project", event: event - else = render "events/event/common", event: event
\ No newline at end of file diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index a9d3adf41df..b0cfba0dea1 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -1,15 +1,17 @@ .event-title %span.author_name= link_to_author event - %span.event_label{class: event.action_name}= event_action_name(event) + %span.event_label{class: event.action_name} + = event_action_name(event) + - if event.target %strong= link_to "##{event.target_iid}", [event.project, event.target] - - else - %strong= gfm event.target_title - at + at + - if event.project = link_to_project event.project - else = event.project_name + - if event.target.respond_to?(:title) .event-body .event-note diff --git a/app/views/events/event/_created_project.html.haml b/app/views/events/event/_created_project.html.haml new file mode 100644 index 00000000000..3c7153d235f --- /dev/null +++ b/app/views/events/event/_created_project.html.haml @@ -0,0 +1,27 @@ +.event-title + %span.author_name= link_to_author event + %span.event_label{class: event.action_name} + = event_action_name(event) + + - if event.project + = link_to_project event.project + - else + = event.project_name + +- if current_user == event.author && !event.project.private? && twitter_sharing_enabled? + .event-body + .event-note + .md + %p + Congratulations! Why not share your accomplishment with the world? + + %a.twitter-share-button{ | + href: "https://twitter.com/share", | + "data-url" => event.project.web_url, | + "data-text" => "I just created a new project in GitLab! GitLab is version control on your server.", | + "data-size" => "medium", | + "data-related" => "gitlab", | + "data-hashtags" => "gitlab", | + "data-count" => "none"} + Tweet + %script{src: "//platform.twitter.com/widgets.js"}
\ No newline at end of file diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml index 6ec8e54fba5..0acb8538778 100644 --- a/app/views/events/event/_note.html.haml +++ b/app/views/events/event/_note.html.haml @@ -1,6 +1,10 @@ .event-title %span.author_name= link_to_author event - %span.event_label commented on #{event_note_title_html(event)} at + %span.event_label + = event.action_name + = event_note_title_html(event) + at + - if event.project = link_to_project event.project - else diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml index b912b5e092f..4b645550517 100644 --- a/app/views/events/event/_push.html.haml +++ b/app/views/events/event/_push.html.haml @@ -1,6 +1,6 @@ .event-title %span.author_name= link_to_author event - %span.event_label.pushed #{event.push_action_name} #{event.ref_type} + %span.event_label.pushed #{event.action_name} #{event.ref_type} - if event.rm_ref? %strong= event.ref_name - else diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 7b8193abfdf..64494e3e6b5 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -42,3 +42,9 @@ %li Use = link_to 'shortcuts', '#', onclick: 'Shortcuts.showHelp(event)' + %li + Get a + = link_to 'support subscription', 'https://about.gitlab.com/pricing/' + %li + = link_to 'Compare', 'https://about.gitlab.com/features/#compare' + GitLab editions diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 98a3d2278a3..422966cdc55 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -17,3 +17,7 @@ = yield = yield :embedded_scripts + +:coffeescript + $('.page-sidebar-collapsed .nav-sidebar a').tooltip placement: "right" + diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index dc8652cb145..e8751a6987e 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Admin area" %body{class: "#{app_theme} #{theme_type} admin", :'data-page' => body_data_page} - = render "layouts/head_panel", title: "Admin area" + = render "layouts/head_panel", title: link_to("Admin area", admin_root_path) = render 'layouts/page', sidebar: 'layouts/nav/admin' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e5420a13605..49123744ffa 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Dashboard" %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page } - = render "layouts/head_panel", title: "Dashboard" + = render "layouts/head_panel", title: link_to("Dashboard", root_path) = render 'layouts/page', sidebar: 'layouts/nav/dashboard' diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml index 9813d846542..09855b222dc 100644 --- a/app/views/layouts/explore.html.haml +++ b/app/views/layouts/explore.html.haml @@ -5,9 +5,9 @@ %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} = render "layouts/broadcast" - if current_user - = render "layouts/head_panel", title: page_title + = render "layouts/head_panel", title: link_to(page_title, explore_root_path) - else - = render "layouts/public_head_panel", title: page_title + = render "layouts/public_head_panel", title: link_to(page_title, explore_root_path) .container.navless-container .content .explore-title diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 98edcf3a140..fa0ed317ce1 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: group_head_title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/head_panel", title: @group.name + = render "layouts/head_panel", title: link_to(@group.name, group_path(@group)) = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 4f864926d08..74334b12e63 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -46,7 +46,7 @@ %span Applications - = nav_link(controller: :application_settings) do + = nav_link(controller: :services) do = link_to admin_application_settings_services_path, title: 'Service Templates' do %i.fa.fa-copy %span diff --git a/app/views/layouts/navless.html.haml b/app/views/layouts/navless.html.haml index 730f3d09277..a3b55542bf7 100644 --- a/app/views/layouts/navless.html.haml +++ b/app/views/layouts/navless.html.haml @@ -3,7 +3,7 @@ = render "layouts/head", title: @title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} = render "layouts/broadcast" - = render "layouts/head_panel", title: @title + = render "layouts/head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title .container.navless-container .content = render "layouts/flash" diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 89d816061e2..19d6efed78e 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Profile" %body{class: "#{app_theme} #{theme_type} profile", :'data-page' => body_data_page} - = render "layouts/head_panel", title: "Profile" + = render "layouts/head_panel", title: link_to("Profile", profile_path) = render 'layouts/page', sidebar: 'layouts/nav/profile' diff --git a/app/views/layouts/public_group.html.haml b/app/views/layouts/public_group.html.haml index ae3d2bd8a89..4b69329b8fe 100644 --- a/app/views/layouts/public_group.html.haml +++ b/app/views/layouts/public_group.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: group_head_title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: "group: #{@group.name}" + = render "layouts/public_head_panel", title: link_to(@group.name, group_path(@group)) = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml index 37767df33d2..3538a8b1699 100644 --- a/app/views/layouts/public_users.html.haml +++ b/app/views/layouts/public_users.html.haml @@ -2,5 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: @title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: @title + = render "layouts/public_head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title = render 'layouts/page' diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml index 6d001e7ee1c..177e2073a0d 100644 --- a/app/views/layouts/search.html.haml +++ b/app/views/layouts/search.html.haml @@ -3,7 +3,7 @@ = render "layouts/head", title: "Search" %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} = render "layouts/broadcast" - = render "layouts/head_panel", title: "Search" + = render "layouts/head_panel", title: link_to("Search", search_path) .container.navless-container .content = render "layouts/flash" diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml index 2a7d317aa3e..6b19db4eb5d 100644 --- a/app/views/profiles/passwords/edit.html.haml +++ b/app/views/profiles/passwords/edit.html.haml @@ -1,25 +1,30 @@ %h3.page-title Password %p.light - Change your password or recover your current one. + - if @user.password_automatically_set? + Set your password. + - else + Change your password or recover your current one. %hr .update-password = form_for @user, url: profile_password_path, method: :put, html: { class: 'form-horizontal' } do |f| %div %p.slead - You must provide current password in order to change it. - %br + - unless @user.password_automatically_set? + You must provide current password in order to change it. + %br After a successful password update you will be redirected to login page where you should login with your new password -if @user.errors.any? .alert.alert-danger %ul - @user.errors.full_messages.each do |msg| %li= msg - .form-group - = f.label :current_password, class: 'control-label' - .col-sm-10 - = f.password_field :current_password, required: true, class: 'form-control' - %div - = link_to "Forgot your password?", reset_profile_password_path, method: :put + - unless @user.password_automatically_set? + .form-group + = f.label :current_password, class: 'control-label' + .col-sm-10 + = f.password_field :current_password, required: true, class: 'form-control' + %div + = link_to "Forgot your password?", reset_profile_password_path, method: :put .form-group = f.label :password, 'New password', class: 'control-label' diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index aef7348fd20..8bed6e0dbee 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -10,10 +10,11 @@ %ul - @user.errors.full_messages.each do |msg| %li= msg - - .form-group - = f.label :current_password, class: 'control-label' - .col-sm-10= f.password_field :current_password, required: true, class: 'form-control' + + - unless @user.password_automatically_set? + .form-group + = f.label :current_password, class: 'control-label' + .col-sm-10= f.password_field :current_password, required: true, class: 'form-control' .form-group = f.label :password, class: 'control-label' .col-sm-10= f.password_field :password, required: true, class: 'form-control' diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index 86ed6bbeaa2..cdcd3d21167 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -15,5 +15,5 @@ %p To preserve performance only %strong #{allowed_diff_size} of #{diffs.size} - files displayed. + files are displayed. diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index d7dee2208de..b925bcb7fac 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -1,5 +1,6 @@ - if current_user && can?(current_user, :download_code, @project) = render 'shared/no_ssh' + = render 'shared/no_password' = render "home_panel" diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 737a34decde..435b2648404 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,5 +1,6 @@ - if current_user && can?(current_user, :download_code, @project) = render 'shared/no_ssh' + = render 'shared/no_password' = render "home_panel" diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 1cc6043f56b..df0bde76980 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,8 +1,20 @@ - project = project || @project .git-clone-holder.input-group .input-group-btn - %button{class: "btn #{ 'active' if default_clone_protocol == 'ssh' }", :"data-clone" => project.ssh_url_to_repo} SSH - %button{class: "btn #{ 'active' if default_clone_protocol == 'http' }", :"data-clone" => project.http_url_to_repo}= gitlab_config.protocol.upcase + %button{ | + class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", | + :"data-clone" => project.ssh_url_to_repo, | + :"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH", + :"data-html" => "true", + :"data-container" => "body"} + SSH + %button{ | + class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.password_automatically_set? }", | + :"data-clone" => project.http_url_to_repo, | + :"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}", + :"data-html" => "true", + :"data-container" => "body"} + = gitlab_config.protocol.upcase = text_field_tag :project_clone, default_url_to_repo(project), class: "one_click_select form-control", readonly: true - if project.kind_of?(Project) .input-group-addon diff --git a/app/views/shared/_no_password.html.haml b/app/views/shared/_no_password.html.haml new file mode 100644 index 00000000000..022097cda16 --- /dev/null +++ b/app/views/shared/_no_password.html.haml @@ -0,0 +1,8 @@ +- if cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && current_user.password_automatically_set? + .no-password-message.alert.alert-warning.hidden-xs + You won't be able to pull or push project code via #{gitlab_config.protocol.upcase} until you #{link_to 'set a password', edit_profile_password_path} on your account + + .pull-right + = link_to "Don't show again", profile_path(user: {hide_no_password: true}), method: :put + | + = link_to 'Remind later', '#', class: 'hide-no-password-message' diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml index 8e6f802fd3b..1a2946baccb 100644 --- a/app/views/shared/_no_ssh.html.haml +++ b/app/views/shared/_no_ssh.html.haml @@ -1,4 +1,4 @@ -- if cookies[:hide_no_ssh_message].blank? && current_user.require_ssh_key? && !current_user.hide_no_ssh_key +- if cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key? .no-ssh-key-message.alert.alert-warning.hidden-xs You won't be able to pull or push project code via SSH until you #{link_to 'add an SSH key', new_profile_key_path} to your profile diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index d7c1a8428ac..6a8bbb80b9c 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -112,6 +112,7 @@ end Settings.gitlab['time_zone'] ||= nil Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? +Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil? diff --git a/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb new file mode 100644 index 00000000000..a0439172391 --- /dev/null +++ b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true + end +end diff --git a/db/migrate/20150213114800_add_hide_no_password_to_user.rb b/db/migrate/20150213114800_add_hide_no_password_to_user.rb new file mode 100644 index 00000000000..685f0844276 --- /dev/null +++ b/db/migrate/20150213114800_add_hide_no_password_to_user.rb @@ -0,0 +1,5 @@ +class AddHideNoPasswordToUser < ActiveRecord::Migration + def change + add_column :users, :hide_no_password, :boolean, default: false + end +end diff --git a/db/migrate/20150213121042_add_password_automatically_set_to_user.rb b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb new file mode 100644 index 00000000000..c3c7c1ffc77 --- /dev/null +++ b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb @@ -0,0 +1,5 @@ +class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration + def change + add_column :users, :password_automatically_set, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index f33766a1fe8..e11a068c9c5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150211174341) do +ActiveRecord::Schema.define(version: 20150213121042) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -26,6 +26,7 @@ ActiveRecord::Schema.define(version: 20150211174341) do t.datetime "updated_at" t.string "home_page_url" t.integer "default_branch_protection", default: 2 + t.boolean "twitter_sharing_enabled", default: true end create_table "broadcast_messages", force: true do |t| @@ -333,10 +334,10 @@ ActiveRecord::Schema.define(version: 20150211174341) do t.string "import_url" t.integer "visibility_level", default: 0, null: false t.boolean "archived", default: false, null: false + t.string "avatar" t.string "import_status" t.float "repository_size", default: 0.0 t.integer "star_count", default: 0, null: false - t.string "avatar" t.string "import_type" t.string "import_source" end @@ -409,12 +410,12 @@ ActiveRecord::Schema.define(version: 20150211174341) do end create_table "users", force: true do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" t.string "current_sign_in_ip" @@ -422,35 +423,37 @@ ActiveRecord::Schema.define(version: 20150211174341) do t.datetime "created_at" t.datetime "updated_at" t.string "name" - t.boolean "admin", default: false, null: false - t.integer "projects_limit", default: 10 - t.string "skype", default: "", null: false - t.string "linkedin", default: "", null: false - t.string "twitter", default: "", null: false + t.boolean "admin", default: false, null: false + t.integer "projects_limit", default: 10 + t.string "skype", default: "", null: false + t.string "linkedin", default: "", null: false + t.string "twitter", default: "", null: false t.string "authentication_token" - t.integer "theme_id", default: 1, null: false + t.integer "theme_id", default: 1, null: false t.string "bio" - t.integer "failed_attempts", default: 0 + t.integer "failed_attempts", default: 0 t.datetime "locked_at" t.string "username" - t.boolean "can_create_group", default: true, null: false - t.boolean "can_create_team", default: true, null: false + t.boolean "can_create_group", default: true, null: false + t.boolean "can_create_team", default: true, null: false t.string "state" - t.integer "color_scheme_id", default: 1, null: false - t.integer "notification_level", default: 1, null: false + t.integer "color_scheme_id", default: 1, null: false + t.integer "notification_level", default: 1, null: false t.datetime "password_expires_at" t.integer "created_by_id" + t.datetime "last_credential_check_at" t.string "avatar" t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" t.string "unconfirmed_email" - t.boolean "hide_no_ssh_key", default: false - t.string "website_url", default: "", null: false - t.datetime "last_credential_check_at" + t.boolean "hide_no_ssh_key", default: false + t.string "website_url", default: "", null: false t.string "github_access_token" t.string "gitlab_access_token" t.string "notification_email" + t.boolean "hide_no_password", default: false + t.boolean "password_automatically_set", default: false end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree diff --git a/doc/README.md b/doc/README.md index 8c6d13e8506..79d4f5273ee 100644 --- a/doc/README.md +++ b/doc/README.md @@ -24,6 +24,7 @@ - [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages. - [Libravatar](customization/libravatar.md) Use Libravatar for user avatars. - [Operations](operations/README.md) Keeping GitLab up and running +- [Log system](logs/logs.md) Log system ## Contributor documentation diff --git a/doc/integration/README.md b/doc/integration/README.md index 0087167bb84..1fc8ab997ec 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -6,8 +6,9 @@ See the documentation below for details on how to configure these services. - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. - [LDAP](ldap.md) Set up sign in via LDAP -- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, and Google via OAuth. +- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth. - [Slack](slack.md) Integrate with the Slack chat service +- [OAuth2 provider](oauth_provider.md) OAuth2 application creation Jenkins support is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jenkins.html). diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md index ba4df9f8fe0..53d6898b6e8 100644 --- a/doc/integration/external-issue-tracker.md +++ b/doc/integration/external-issue-tracker.md @@ -1,13 +1,38 @@ # External issue tracker -GitLab has a great issue tracker but you can also use an external issue tracker such as JIRA, Bugzilla or Redmine. This is something that you can turn on per GitLab project. If for example you configure JIRA it provides the following functionality: +GitLab has a great issue tracker but you can also use an external issue tracker such as Jira, Bugzilla or Redmine. You can configure issue trackers per GitLab project. For instance, if you configure Jira it allows you to do the following: -- the 'Issues' link on the GitLab project pages takes you to the appropriate JIRA issue index; -- clicking 'New issue' on the project dashboard creates a new JIRA issue; -- To reference JIRA issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding JIRA issue. +- the 'Issues' link on the GitLab project pages takes you to the appropriate Jira issue index; +- clicking 'New issue' on the project dashboard creates a new Jira issue; +- To reference Jira issue PROJECT-1234 in comments, use syntax PROJECT-1234. Commit messages get turned into HTML links to the corresponding Jira issue.  -You can configure the integration in the gitlab.yml configuration file. +## Configuration + +### Project Service + +You can enable an external issue tracker per project. As an example, we will configure `Redmine` for project named gitlab-ci. + +Fill in the required details on the page: + + + +* `description` A name for the issue tracker (to differentiate between instances, for example). +* `project_url` The URL to the project in Redmine which is being linked to this GitLab project. +* `issues_url` The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the url. This id is used by GitLab as a placeholder to replace the issue number. +* `new_issue_url` This is the URL to create a new issue in Redmine for the project linked to this GitLab project. + + +### Service Template + +It is necessary to configure the external issue tracker per project, because project specific details are needed for the integration with GitLab. +The admin can add a service template that sets a default for each project. This makes it much easier to configure individual projects. + +In GitLab Admin section, navigate to `Service Templates` and choose the service template you want to create: + + + +After the template is created, the template details will be pre-filled on the project service page. Support to add your commits to the Jira ticket automatically is [available in GitLab EE](http://doc.gitlab.com/ee/integration/jira.html). diff --git a/doc/integration/github.md b/doc/integration/github.md index a586334b98d..c9c27859c5e 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -21,20 +21,44 @@ To enable the GitHub OmniAuth provider you must register your application with G 1. On your GitLab server, open the configuration file. + For omnibus package: + + ```sh + sudo editor /etc/gitlab/gitlab.rb + ``` + + For instalations from source: + ```sh - cd /home/git/gitlab + cd /home/git/gitlab - sudo -u git -H editor config/gitlab.yml + sudo -u git -H editor config/gitlab.yml ``` -1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. +1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings. + +1. Add the provider configuration: + + For omnibus package: + + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + "name" => "github", + "app_id" => "YOUR APP ID", + "app_secret" => "YOUR APP SECRET", + "url" => "https://github.com/", + "args" => { "scope" => "user:email" } } + } + ] + ``` -1. Under `providers:` uncomment (or add) lines that look like the following: + For installation from source: ``` - - { name: 'github', app_id: 'YOUR APP ID', - app_secret: 'YOUR APP SECRET', - args: { scope: 'user:email' } } + - { name: 'github', app_id: 'YOUR APP ID', + app_secret: 'YOUR APP SECRET', + args: { scope: 'user:email' } } ``` 1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md index b3b1d897225..b95ef5c0af3 100644 --- a/doc/integration/gitlab.md +++ b/doc/integration/gitlab.md @@ -12,35 +12,60 @@ To enable the GitLab OmniAuth provider you must register your application with G 1. Provide the required details. - Name: This can be anything. Consider something like "\<Organization\>'s GitLab" or "\<Your Name\>'s GitLab" or something else descriptive. - - Redirect URI: - + - Redirect URI: + ``` http://gitlab.example.com/import/gitlab/callback http://gitlab.example.com/users/auth/gitlab/callback ``` - The first link is required for the importer and second for the authorization. + The first link is required for the importer and second for the authorization. 1. Select "Submit". 1. You should now see a Application ID and Secret. Keep this page open as you continue configuration. +1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration.  + 1. On your GitLab server, open the configuration file. + For omnibus package: + ```sh - cd /home/git/gitlab + sudo editor /etc/gitlab/gitlab.rb + ``` + + For instalations from source: - sudo -u git -H editor config/gitlab.yml + ```sh + cd /home/git/gitlab + + sudo -u git -H editor config/gitlab.yml ``` -1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. +1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings. + +1. Add the provider configuration: + + For omnibus package: + + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + "name" => "gitlab", + "app_id" => "YOUR APP ID", + "app_secret" => "YOUR APP SECRET", + "args" => { "scope" => "api" } } + } + ] + ``` -1. Under `providers:` uncomment (or add) lines that look like the following: + For installations from source: ``` - - { name: 'gitlab', app_id: 'YOUR APP ID', - app_secret: 'YOUR APP SECRET', - args: { scope: 'api' } } + - { name: 'gitlab', app_id: 'YOUR APP ID', + app_secret: 'YOUR APP SECRET', + args: { scope: 'api' } } ``` 1. Change 'YOUR APP ID' to the Application ID from the GitLab application page. diff --git a/doc/integration/google.md b/doc/integration/google.md index 7a78aff8ea4..168077c2770 100644 --- a/doc/integration/google.md +++ b/doc/integration/google.md @@ -27,27 +27,50 @@ To enable the Google OAuth2 OmniAuth provider you must register your application - Authorized redirect URI: 'https://gitlab.example.com/users/auth/google_oauth2/callback' 1. Under the heading "Client ID for web application" you should see a Client ID and Client secret (see screenshot). Keep this page open as you continue configuration.  -1. On your GitLab server, open the configuration file. +1. On your GitLab server, open the configuration file. + + For omnibus package: + + ```sh + sudo editor /etc/gitlab/gitlab.rb + ``` + + For instalations from source: ```sh - cd /home/git/gitlab + cd /home/git/gitlab - sudo -u git -H editor config/gitlab.yml + sudo -u git -H editor config/gitlab.yml ``` -1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details. +1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings. + +1. Add the provider configuration: + + For omnibus package: + + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + "name" => "google_oauth2", + "app_id" => "YOUR APP ID", + "app_secret" => "YOUR APP SECRET", + "args" => { "access_type" => "offline", "approval_prompt" => '' } } + } + ] + ``` -1. Under `providers:` uncomment (or add) lines that look like the following: + For installations from source: ``` - - { name: 'google_oauth2', app_id: 'YOUR APP ID', - app_secret: 'YOUR APP SECRET', - args: { access_type: 'offline', approval_prompt: '' } } + - { name: 'google_oauth2', app_id: 'YOUR APP ID', + app_secret: 'YOUR APP SECRET', + args: { access_type: 'offline', approval_prompt: '' } } ``` -1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7. +1. Change 'YOUR APP ID' to the client ID from the Google Developer page from step 10. -1. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7. +1. Change 'YOUR APP SECRET' to the client secret from the Google Developer page from step 10. 1. Save the configuration file. diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md new file mode 100644 index 00000000000..5fdb74a43df --- /dev/null +++ b/doc/integration/oauth_provider.md @@ -0,0 +1,31 @@ +## GitLab as OAuth2 provider +OAuth2 provides client applications a 'secure delegated access' to server resources on behalf of a resource owner. Or you can allow users to sign in to your application with their GitLab.com account. +In fact OAuth allows to issue access token to third-party clients by an authorization server, +with the approval of the resource owner, or end-user. +Mostly, OAuth2 is using for SSO (Single sign-on). But you can find a lot of different usages for this functionality. +For example, our feature 'GitLab Importer' is using OAuth protocol to give an access to repositories without sharing user credentials to GitLab.com account. +Also GitLab.com application can be used for authentication to your GitLab instance if needed [GitLab OmniAuth](gitlab.md). + +GitLab has two ways to add new OAuth2 application to an instance, you can add application as regular user and through admin area. So GitLab actually can have an instance-wide and a user-wide applications. There is no defferences between them except the different permission levels. + +### Adding application through profile +Go to your profile section 'Application' and press button 'New Application' + + + +After this you will see application form, where "Name" is arbitrary name, "Redirect URI" is URL in your app where users will be sent after authorization on GitLab.com. + + + +### Authorized application +Every application you authorized will be shown in your "Authorized application" sections. + + + +At any time you can revoke access just clicking button "Revoke" + +### OAuth applications in admin area + +If you want to create application that does not belong to certain user you can create it from admin area + +
\ No newline at end of file diff --git a/doc/integration/oauth_provider/admin_application.png b/doc/integration/oauth_provider/admin_application.png Binary files differnew file mode 100644 index 00000000000..a5f34512aa8 --- /dev/null +++ b/doc/integration/oauth_provider/admin_application.png diff --git a/doc/integration/oauth_provider/application_form.png b/doc/integration/oauth_provider/application_form.png Binary files differnew file mode 100644 index 00000000000..ae135db2627 --- /dev/null +++ b/doc/integration/oauth_provider/application_form.png diff --git a/doc/integration/oauth_provider/authorized_application.png b/doc/integration/oauth_provider/authorized_application.png Binary files differnew file mode 100644 index 00000000000..d3ce05be9cc --- /dev/null +++ b/doc/integration/oauth_provider/authorized_application.png diff --git a/doc/integration/oauth_provider/user_wide_applications.png b/doc/integration/oauth_provider/user_wide_applications.png Binary files differnew file mode 100644 index 00000000000..719e1974068 --- /dev/null +++ b/doc/integration/oauth_provider/user_wide_applications.png diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 15b4fb622af..7433de33909 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -1,8 +1,8 @@ # OmniAuth -GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and other popular services. Configuring +GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and other popular services. -OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can choose to sign in using any of the configured mechanisms. +Configuring OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) from continuing to work. Users can choose to sign in using any of the configured mechanisms. - [Initial OmniAuth Configuration](#initial-omniauth-configuration) - [Supported Providers](#supported-providers) @@ -11,9 +11,37 @@ OmniAuth does not prevent standard GitLab authentication or LDAP (if configured) ## Initial OmniAuth Configuration -Before configuring individual OmniAuth providers there are a few global settings that need to be verified. +Before configuring individual OmniAuth providers there are a few global settings that are in common for all providers that we need to consider. -1. Open the configuration file. +- Omniauth needs to be enabled, see details below for example. +- `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to +sign in via OmniAuth. +- `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will +have to be unblocked by an administrator before they are able to sign in. +- **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware +that any user on the Internet will be able to successfully sign in to your GitLab without administrative approval. + +If you want to change these settings: + +* **For omnibus package** + + Open the configuration file: + + ```sh + sudo editor /etc/gitlab/gitlab.rb + ``` + + and change + + ``` + gitlab_rails['omniauth_enabled'] = true + gitlab_rails['omniauth_allow_single_sign_on'] = false + gitlab_rails['block_auto_created_users'] = true + ``` + +* **For installations from source** + + Open the configuration file: ```sh cd /home/git/gitlab @@ -21,13 +49,13 @@ Before configuring individual OmniAuth providers there are a few global settings sudo -u git -H editor config/gitlab.yml ``` -1. Find the section dealing with OmniAuth. The section will look similar to the following. + and change the following section ``` - ## OmniAuth settings + ## OmniAuth settings omniauth: # Allow login via Twitter, Google, etc. using OmniAuth providers - enabled: false + enabled: true # CAUTION! # This allows users to login without having a user account first (default: false). @@ -35,47 +63,14 @@ Before configuring individual OmniAuth providers there are a few global settings allow_single_sign_on: false # Locks down those users until they have been cleared by the admin (default: true). block_auto_created_users: true - - ## Auth providers - # Uncomment the following lines and fill in the data of the auth provider you want to use - # If your favorite auth provider is not listed you can use others: - # see https://github.com/gitlabhq/gitlab-public-wiki/wiki/Custom-omniauth-provider-configurations - # The 'app_id' and 'app_secret' parameters are always passed as the first two - # arguments, followed by optional 'args' which can be either a hash or an array. - providers: - # - { name: 'google_oauth2', app_id: 'YOUR APP ID', - # app_secret: 'YOUR APP SECRET', - # args: { access_type: 'offline', approval_prompt: '' } } - # - { name: 'twitter', app_id: 'YOUR APP ID', - # app_secret: 'YOUR APP SECRET'} - # - { name: 'github', app_id: 'YOUR APP ID', - # app_secret: 'YOUR APP SECRET', - # args: { scope: 'user:email' } } - # - {"name": 'shibboleth', - # args: { shib_session_id_field: "HTTP_SHIB_SESSION_ID", - # shib_application_id_field: "HTTP_SHIB_APPLICATION_ID", - # uid_field: "HTTP_EPPN", - # name_field: "HTTP_CN", - # info_fields: {"email": "HTTP_MAIL" } } } - ``` -1. Change `enabled` to `true`. - -1. Consider the next two configuration options: `allow_single_sign_on` and `block_auto_created_users`. - - - `allow_single_sign_on` defaults to `false`. If `false` users must be created manually or they will not be able to - sign in via OmniAuth. - - `block_auto_created_users` defaults to `true`. If `true` auto created users will be blocked by default and will - have to be unblocked by an administrator before they are able to sign in. - - **Note:** If you set `allow_single_sign_on` to `true` and `block_auto_created_users` to `false` please be aware - that any user on the Internet will be able to successfully sign in to your GitLab without administrative approval. - -1. Choose one or more of the Supported Providers below to continue configuration. +Now we can choose one or more of the Supported Providers below to continue configuration. ## Supported Providers - [GitHub](github.md) +- [GitLab](gitlab.md) - [Google](google.md) - [Shibboleth](shibboleth.md) - [Twitter](twitter.md) diff --git a/doc/integration/redmine_configuration.png b/doc/integration/redmine_configuration.png Binary files differnew file mode 100644 index 00000000000..6b145363229 --- /dev/null +++ b/doc/integration/redmine_configuration.png diff --git a/doc/integration/redmine_service_template.png b/doc/integration/redmine_service_template.png Binary files differnew file mode 100644 index 00000000000..1159eb5b964 --- /dev/null +++ b/doc/integration/redmine_service_template.png diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md index ea11f1afeab..6258e5f1030 100644 --- a/doc/integration/shibboleth.md +++ b/doc/integration/shibboleth.md @@ -2,12 +2,12 @@ This documentation is for enabling shibboleth with gitlab-omnibus package. -In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however I did not found way to easily configure Nginx that is bundled in gitlab-omnibus package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider. +In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however I did not found way to easily configure Nginx that is bundled in gitlab-omnibus package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider. To enable the Shibboleth OmniAuth provider you must: -1. Configure Apache shibboleth module. Installation and configuration of module it self is out of scope of this document. +1. Configure Apache shibboleth module. Installation and configuration of module it self is out of scope of this document. Check https://wiki.shibboleth.net/ for more info. 1. You can find Apache config in gitlab-recipes (https://github.com/gitlabhq/gitlab-recipes/blob/master/web-server/apache/gitlab-ssl.conf) @@ -37,15 +37,15 @@ exclude shibboleth URLs from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibbo # Apache equivalent of Nginx try files RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_URI} !/Shibboleth.sso - RewriteCond %{REQUEST_URI} !/shibboleth-sp + RewriteCond %{REQUEST_URI} !/Shibboleth.sso + RewriteCond %{REQUEST_URI} !/shibboleth-sp RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA] RequestHeader set X_FORWARDED_PROTO 'https' ``` -1. Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should addjust them to your need and environment. Add any other configuration you need. +1. Edit /etc/gitlab/gitlab.rb configuration file, your shibboleth attributes should be in form of "HTTP_ATTRIBUTE" and you should addjust them to your need and environment. Add any other configuration you need. -File it should look like this: +File should look like this: ``` external_url 'https://gitlab.example.com' gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' @@ -70,7 +70,7 @@ gitlab_rails['omniauth_providers'] = [ ] ``` -1. Save changes and reconfigure gitlab: +1. Save changes and reconfigure gitlab: ``` sudo gitlab-ctl reconfigure ``` diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md index b9e501c5ec1..2d517b2fbc9 100644 --- a/doc/integration/twitter.md +++ b/doc/integration/twitter.md @@ -33,20 +33,41 @@ To enable the Twitter OmniAuth provider you must register your application with 1. On your GitLab server, open the configuration file. + For omnibus package: + + ```sh + sudo editor /etc/gitlab/gitlab.rb + ``` + + For instalations from source: + ```sh - cd /home/git/gitlab + cd /home/git/gitlab - sudo -u git -H editor config/gitlab.yml + sudo -u git -H editor config/gitlab.yml ``` -1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) -for more details. +1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings. + +1. Add the provider configuration: + + For omnibus package: + + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + "name" => "twitter", + "app_id" => "YOUR APP ID", + "app_secret" => "YOUR APP SECRET" + } + ] + ``` -1. Under `providers:` uncomment (or add) lines that look like the following: + For installations from source: ``` - - { name: 'twitter', app_id: 'YOUR APP ID', - app_secret: 'YOUR APP SECRET' } + - { name: 'twitter', app_id: 'YOUR APP ID', + app_secret: 'YOUR APP SECRET' } ``` 1. Change 'YOUR APP ID' to the API key from Twitter page in step 11. diff --git a/doc/logs/logs.md b/doc/logs/logs.md new file mode 100644 index 00000000000..07302894dd4 --- /dev/null +++ b/doc/logs/logs.md @@ -0,0 +1,100 @@ +## Log system +GitLab has advanced log system so everything is logging and you can analize your instance using various system log files. +These log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files. + +#### production.log +This file lives in `/var/log/gitlab/gitlab-rails/production.log` for omnibus package or in `/home/git/gitlab/logs/production.log` for installations from the source. + +This file contains information about all performed requests. You can see url and type of request, IP address and what exactly parts of code were involved to service this particular request. Also you can see all SQL request that have been performed and how much time it took. +This task is more useful for GitLab contributors and developers. Use part of this log file when you are going to report bug. + +``` +Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200 +Processing by Projects::TreeController#show as HTML + Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"} + + ... [CUT OUT] + + amespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1[0m [["id", 26]] + [1m[35mCACHE (0.0ms)[0m SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]] + [1m[36mCACHE (0.0ms)[0m [1mSELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members". + [1m[36m (1.4ms)[0m [1mSELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened'))[0m [["target_project_id", 18]] + Rendered layouts/nav/_project.html.haml (28.0ms) + Rendered layouts/_collapse_button.html.haml (0.2ms) + Rendered layouts/_flash.html.haml (0.1ms) + Rendered layouts/_page.html.haml (32.9ms) +Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms) +``` +In this example we can see that server processed HTTP request with url `/gitlabhq/yaml_db/tree/master` from IP 168.111.56.1 at 2015-02-12 19:34:53 +0200. Also we can see that request was processed by Projects::TreeController. + +#### application.log +This file lives in `/var/log/gitlab/gitlab-rails/application.log` for omnibus package or in `/home/git/gitlab/logs/application.log` for installations from the source. + +This log file helps you discover events happening in your instance such as user creation, project removing and so on. + +``` +October 06, 2014 11:56: User "Administrator" (admin@example.com) was created +October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore" +October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce" +October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was removed +October 07, 2014 11:25: Project "project133" was removed +``` +#### githost.log +This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for omnibus package or in `/home/git/gitlab/logs/githost.log` for installations from the source. + +The GitLab has to interact with git repositories but in some rare cases something can go wrong and in this case you will know what exactly happened. This log file contains all failed requests from GitLab to git repository. In majority of cases this file will be useful for developers only. +``` +December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict + +error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git' +``` + +#### satellites.log +This file lives in `/var/log/gitlab/gitlab-rails/satellites.log` for omnibus package or in `/home/git/gitlab/logs/satellites.log` for installations from the source. + +In some cases GitLab should perform write actions to git repository, for example when it is needed to merge the merge request or edit a file with online editor. If something went wrong you can look into this file to find out what exactly happened. +``` +October 07, 2014 11:36: Failed to create satellite for Chesley Weimann III / project1817 +October 07, 2014 11:36: PID: 1872: git clone /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/conrad6841/gitlabhq +October 07, 2014 11:36: PID: 1872: -> fatal: repository '/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git' does not exist +``` + +#### sidekiq.log +This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for omnibus package or in `/home/git/gitlab/logs/sidekiq.log` for installations from the source. + +GitLab uses background jobs for processing tasks which can take a long time. All information about processing these jobs are writing down to this file. +``` +2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read' +2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"} +``` + +#### gitlab-shell.log +This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for omnibus package or in `/home/git/gitlab-shell/logs/sidekiq.log` for installations from the source. + +gitlab-shell is using by Gitlab for executing git commands and provide ssh access to git repositories. + +``` +I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at </var/opt/gitlab/git-data/repositories/root/dcdcdcdcd.git>. +I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and simlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git. +``` + +#### unicorn_stderr.log +This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/logs/unicorn_stderr.log` for installations from the source. + +Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time. + +``` +I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list +I, [2015-02-13T06:14:56.931002 #9047] INFO -- : listening on addr=127.0.0.1:8080 fd=12 +I, [2015-02-13T06:14:56.931381 #9047] INFO -- : listening on addr=/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket fd=13 +I, [2015-02-13T06:14:56.936638 #9047] INFO -- : master process ready +I, [2015-02-13T06:14:56.946504 #9092] INFO -- : worker=0 spawned pid=9092 +I, [2015-02-13T06:14:56.946943 #9092] INFO -- : worker=0 ready +I, [2015-02-13T06:14:56.947892 #9094] INFO -- : worker=1 spawned pid=9094 +I, [2015-02-13T06:14:56.948181 #9094] INFO -- : worker=1 ready +W, [2015-02-13T07:16:01.312916 #9094] WARN -- : #<Unicorn::HttpServer:0x0000000208f618>: worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes) +W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1) +I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped #<Process::Status: pid 9094 exit 0> worker=1 +I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379 +I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready +``` diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 3c0007d8198..6e70235f5b8 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -9,5 +9,6 @@ - [Notifications](notifications.md) - [Migrating from SVN to GitLab](migrating_from_svn.md) - [Project importing from GitHub to GitLab](import_projects_from_github.md) +- [Project importing from GitLab.com to your private GitLab instance](import_projects_from_gitlab_com.md) - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) diff --git a/doc/workflow/gitlab_importer/importer.png b/doc/workflow/gitlab_importer/importer.png Binary files differnew file mode 100644 index 00000000000..d2a286d8cac --- /dev/null +++ b/doc/workflow/gitlab_importer/importer.png diff --git a/doc/workflow/gitlab_importer/new_project_page.png b/doc/workflow/gitlab_importer/new_project_page.png Binary files differnew file mode 100644 index 00000000000..5e239208e1e --- /dev/null +++ b/doc/workflow/gitlab_importer/new_project_page.png diff --git a/doc/workflow/import_projects_from_gitlab_com.md b/doc/workflow/import_projects_from_gitlab_com.md new file mode 100644 index 00000000000..f4c4e955d46 --- /dev/null +++ b/doc/workflow/import_projects_from_gitlab_com.md @@ -0,0 +1,18 @@ +# Project importing from GitLab.com to your private GitLab instance + +You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if +GitLab support is enabled on your GitLab instance. +You can read more about Gitlab support [here](http://doc.gitlab.com/ce/integration/gitlab.html) +To get to the importer page you need to go to "New project" page. + + + +Click on the "Import projects from Gitlab.com" link and you will be redirected to GitLab.com +for permission to access your projects. After accepting, you'll be automatically redirected to the importer. + + + + + +To import a project, you can simple click "Import". The importer will import your repository and issues. +Once the importer is done, a new GitLab project will be created with your imported data.
\ No newline at end of file diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature index bebaa78e46c..1959d327082 100644 --- a/features/dashboard/dashboard.feature +++ b/features/dashboard/dashboard.feature @@ -27,11 +27,11 @@ Feature: Dashboard Scenario: I should see User joined Project event Given user with name "John Doe" joined project "Shop" When I visit dashboard page - Then I should see "John Doe joined project at Shop" event + Then I should see "John Doe joined project Shop" event @javascript Scenario: I should see User left Project event Given user with name "John Doe" joined project "Shop" And user with name "John Doe" left project "Shop" When I visit dashboard page - Then I should see "John Doe left project at Shop" event + Then I should see "John Doe left project Shop" event diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb index 1826ead1d51..961f8b284b8 100644 --- a/features/steps/dashboard/dashboard.rb +++ b/features/steps/dashboard/dashboard.rb @@ -37,8 +37,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps ) end - step 'I should see "John Doe joined project at Shop" event' do - page.should have_content "John Doe joined project at #{project.name_with_namespace}" + step 'I should see "John Doe joined project Shop" event' do + page.should have_content "John Doe joined project #{project.name_with_namespace}" end step 'user with name "John Doe" left project "Shop"' do @@ -50,8 +50,8 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps ) end - step 'I should see "John Doe left project at Shop" event' do - page.should have_content "John Doe left project at #{project.name_with_namespace}" + step 'I should see "John Doe left project Shop" event' do + page.should have_content "John Doe left project #{project.name_with_namespace}" end step 'I have group with projects' do diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb index 9f55e8c4950..c023d275703 100644 --- a/lib/gitlab/oauth/user.rb +++ b/lib/gitlab/oauth/user.rb @@ -85,11 +85,12 @@ module Gitlab def user_attributes { - name: auth_hash.name, - username: ::User.clean_username(auth_hash.username), - email: auth_hash.email, - password: auth_hash.password, - password_confirmation: auth_hash.password + name: auth_hash.name, + username: ::User.clean_username(auth_hash.username), + email: auth_hash.email, + password: auth_hash.password, + password_confirmation: auth_hash.password, + password_automatically_set: true } end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6102b2e30be..c015a1d2687 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -303,8 +303,8 @@ describe User do describe ".clean_username" do - let!(:user1) { create(:user, username: "johngitlab-etc") } - let!(:user2) { create(:user, username: "JohnGitLab-etc1") } + let!(:user) { create(:user, username: "johngitlab-etc") } + let!(:namespace) { create(:namespace, path: "JohnGitLab-etc1") } it "cleans a username and makes sure it's available" do expect(User.clean_username("-john+gitlab-ETC%.git@gmail.com")).to eq("johngitlab-ETC2") diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 170ede57310..0b3a47e3273 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -347,7 +347,7 @@ describe API::API, api: true do end describe 'GET /projects/:id/events' do - before { project_member } + before { project_member2 } it 'should return a project events' do get api("/projects/#{project.id}/events", user) @@ -356,7 +356,7 @@ describe API::API, api: true do expect(json_event['action_name']).to eq('joined') expect(json_event['project_id'].to_i).to eq(project.id) - expect(json_event['author_username']).to eq(user.username) + expect(json_event['author_username']).to eq(user3.username) end it 'should return a 404 error if not found' do |