summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG6
-rw-r--r--app/assets/stylesheets/sections/login.scss3
-rw-r--r--app/controllers/projects/services_controller.rb2
-rw-r--r--app/controllers/snippets_controller.rb1
-rw-r--r--app/controllers/users_controller.rb1
-rw-r--r--app/models/namespace.rb4
-rw-r--r--app/models/project_services/issue_tracker_service.rb23
-rw-r--r--app/models/project_services/jira_service.rb14
-rw-r--r--app/models/user.rb5
-rw-r--r--app/views/admin/services/_form.html.haml4
-rw-r--r--app/views/dashboard/_zero_authorized_projects.html.haml8
-rw-r--r--app/views/dashboard/projects.html.haml4
-rw-r--r--app/views/devise/registrations/new.html.haml6
-rw-r--r--app/views/devise/sessions/new.html.haml9
-rw-r--r--app/views/devise/shared/_oauth_box.html.haml10
-rw-r--r--app/views/devise/shared/_signin_box.html.haml21
-rw-r--r--app/views/devise/shared/_signup_box.html.haml13
-rw-r--r--app/views/layouts/admin.html.haml2
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/layouts/explore.html.haml4
-rw-r--r--app/views/layouts/group.html.haml2
-rw-r--r--app/views/layouts/nav/_admin.html.haml2
-rw-r--r--app/views/layouts/navless.html.haml2
-rw-r--r--app/views/layouts/profile.html.haml2
-rw-r--r--app/views/layouts/public_group.html.haml2
-rw-r--r--app/views/layouts/public_users.html.haml2
-rw-r--r--app/views/layouts/search.html.haml2
-rw-r--r--doc/README.md1
-rw-r--r--doc/integration/README.md3
-rw-r--r--doc/integration/external-issue-tracker.md35
-rw-r--r--doc/integration/oauth_provider.md31
-rw-r--r--doc/integration/oauth_provider/admin_application.pngbin0 -> 55533 bytes
-rw-r--r--doc/integration/oauth_provider/application_form.pngbin0 -> 25075 bytes
-rw-r--r--doc/integration/oauth_provider/authorized_application.pngbin0 -> 17260 bytes
-rw-r--r--doc/integration/oauth_provider/user_wide_applications.pngbin0 -> 46238 bytes
-rw-r--r--doc/integration/redmine_configuration.pngbin0 -> 118752 bytes
-rw-r--r--doc/integration/redmine_service_template.pngbin0 -> 198077 bytes
-rw-r--r--doc/logs/logs.md100
-rw-r--r--spec/models/user_spec.rb4
39 files changed, 273 insertions, 57 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ead51cb3c8a..0bf8de6bd17 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,6 +50,8 @@ 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).
v 7.7.2
@@ -86,9 +88,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/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/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/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/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 23d1e69e69a..5f98bfb7870 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -254,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
@@ -292,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/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 &nbsp;
- - 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 &nbsp;
+ - 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/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/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.
![Jira screenshot](jira-integration-points.png)
-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:
+
+![redmine configuration](redmine_configuration.png)
+
+* `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:
+
+![redmine service template](redmine_service_template.png)
+
+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/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'
+
+![applications](oauth_provider/user_wide_applications.png)
+
+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.
+
+![application_form](oauth_provider/application_form.png)
+
+### Authorized application
+Every application you authorized will be shown in your "Authorized application" sections.
+
+![authorized_application](oauth_provider/authorized_application.png)
+
+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
+
+![admin_application](oauth_provider/admin_application.png) \ No newline at end of file
diff --git a/doc/integration/oauth_provider/admin_application.png b/doc/integration/oauth_provider/admin_application.png
new file mode 100644
index 00000000000..a5f34512aa8
--- /dev/null
+++ b/doc/integration/oauth_provider/admin_application.png
Binary files differ
diff --git a/doc/integration/oauth_provider/application_form.png b/doc/integration/oauth_provider/application_form.png
new file mode 100644
index 00000000000..ae135db2627
--- /dev/null
+++ b/doc/integration/oauth_provider/application_form.png
Binary files differ
diff --git a/doc/integration/oauth_provider/authorized_application.png b/doc/integration/oauth_provider/authorized_application.png
new file mode 100644
index 00000000000..d3ce05be9cc
--- /dev/null
+++ b/doc/integration/oauth_provider/authorized_application.png
Binary files differ
diff --git a/doc/integration/oauth_provider/user_wide_applications.png b/doc/integration/oauth_provider/user_wide_applications.png
new file mode 100644
index 00000000000..719e1974068
--- /dev/null
+++ b/doc/integration/oauth_provider/user_wide_applications.png
Binary files differ
diff --git a/doc/integration/redmine_configuration.png b/doc/integration/redmine_configuration.png
new file mode 100644
index 00000000000..6b145363229
--- /dev/null
+++ b/doc/integration/redmine_configuration.png
Binary files differ
diff --git a/doc/integration/redmine_service_template.png b/doc/integration/redmine_service_template.png
new file mode 100644
index 00000000000..1159eb5b964
--- /dev/null
+++ b/doc/integration/redmine_service_template.png
Binary files differ
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 [["id", 26]]
+ CACHE (0.0ms) 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"]]
+ CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members".
+  (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["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/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")