Commit 76f2e065 authored by Sytse Sijbrandij's avatar Sytse Sijbrandij

Merge branch 'master' into install-guide-improvements

Conflicts:
	doc/install/installation.md
parents 8ccad7c3 48d37272
...@@ -24,6 +24,7 @@ v 5.3.0 ...@@ -24,6 +24,7 @@ v 5.3.0
- init.d: Ensure socket is removed before starting service - init.d: Ensure socket is removed before starting service
- Admin area: Style teams:index, group:show pages - Admin area: Style teams:index, group:show pages
- Own page for failed forking - Own page for failed forking
- Scrum view for milestone
v 5.2.0 v 5.2.0
- Turbolinks - Turbolinks
......
...@@ -29,7 +29,7 @@ gem 'gitlab_git', '~> 1.3.0' ...@@ -29,7 +29,7 @@ gem 'gitlab_git', '~> 1.3.0'
gem 'gitlab-grack', '~> 1.0.1', require: 'grack' gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
# LDAP Auth # LDAP Auth
gem 'gitlab_omniauth-ldap', '1.0.2', require: "omniauth-ldap" gem 'gitlab_omniauth-ldap', '1.0.3', require: "omniauth-ldap"
# Syntax highlighter # Syntax highlighter
gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb' gem "gitlab-pygments.rb", '~> 0.3.2', require: 'pygments.rb'
...@@ -72,6 +72,9 @@ gem "seed-fu" ...@@ -72,6 +72,9 @@ gem "seed-fu"
gem "redcarpet", "~> 2.2.2" gem "redcarpet", "~> 2.2.2"
gem "github-markup", "~> 0.7.4", require: 'github/markup' gem "github-markup", "~> 0.7.4", require: 'github/markup'
# Asciidoc to HTML
gem "asciidoctor"
# Servers # Servers
gem "puma", '~> 2.0.1' gem "puma", '~> 2.0.1'
......
...@@ -46,6 +46,7 @@ GEM ...@@ -46,6 +46,7 @@ GEM
rails (~> 3.0) rails (~> 3.0)
addressable (2.3.4) addressable (2.3.4)
arel (3.0.2) arel (3.0.2)
asciidoctor (0.1.3)
awesome_print (1.1.0) awesome_print (1.1.0)
backports (2.6.7) backports (2.6.7)
bcrypt-ruby (3.0.1) bcrypt-ruby (3.0.1)
...@@ -168,8 +169,8 @@ GEM ...@@ -168,8 +169,8 @@ GEM
github-linguist (~> 2.3.4) github-linguist (~> 2.3.4)
gitlab-grit (~> 2.5.1) gitlab-grit (~> 2.5.1)
gitlab_meta (5.0) gitlab_meta (5.0)
gitlab_omniauth-ldap (1.0.2) gitlab_omniauth-ldap (1.0.3)
net-ldap (~> 0.2.2) net-ldap (~> 0.3.1)
omniauth (~> 1.0) omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1) pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1) rubyntlm (~> 0.1.1)
...@@ -265,7 +266,7 @@ GEM ...@@ -265,7 +266,7 @@ GEM
multi_xml (0.5.3) multi_xml (0.5.3)
multipart-post (1.2.0) multipart-post (1.2.0)
mysql2 (0.3.11) mysql2 (0.3.11)
net-ldap (0.2.2) net-ldap (0.3.1)
nokogiri (1.5.9) nokogiri (1.5.9)
oauth (0.4.7) oauth (0.4.7)
oauth2 (0.8.1) oauth2 (0.8.1)
...@@ -517,6 +518,7 @@ PLATFORMS ...@@ -517,6 +518,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
acts-as-taggable-on acts-as-taggable-on
annotate! annotate!
asciidoctor
awesome_print awesome_print
better_errors better_errors
binding_of_caller binding_of_caller
...@@ -544,7 +546,7 @@ DEPENDENCIES ...@@ -544,7 +546,7 @@ DEPENDENCIES
gitlab-pygments.rb (~> 0.3.2) gitlab-pygments.rb (~> 0.3.2)
gitlab_git (~> 1.3.0) gitlab_git (~> 1.3.0)
gitlab_meta (= 5.0) gitlab_meta (= 5.0)
gitlab_omniauth-ldap (= 1.0.2) gitlab_omniauth-ldap (= 1.0.3)
gon gon
grape (~> 0.4.1) grape (~> 0.4.1)
grape-entity (~> 0.3.0) grape-entity (~> 0.3.0)
......
$ ->
$('.milestone-issue-filter li[data-closed]').addClass('hide')
$('.milestone-issue-filter ul.nav li a').click ->
$('.milestone-issue-filter li').toggleClass('active')
$('.milestone-issue-filter li[data-closed]').toggleClass('hide')
false
$('.milestone-merge-requests-filter li[data-closed]').addClass('hide')
$('.milestone-merge-requests-filter ul.nav li a').click ->
$('.milestone-merge-requests-filter li').toggleClass('active')
$('.milestone-merge-requests-filter li[data-closed]').toggleClass('hide')
false
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
border-color: #CCC; border-color: #CCC;
border-bottom: 1px solid #fff; border-bottom: 1px solid #fff;
color: #333; color: #333;
font-weight: bold;
} }
} }
} }
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
background: #f9f9f9; background: #f9f9f9;
border-radius: 0; border-radius: 0;
color: #555; color: #555;
margin: 0 20px;
} }
.note-file-attach { .note-file-attach {
......
...@@ -92,6 +92,10 @@ ul.notes { ...@@ -92,6 +92,10 @@ ul.notes {
.note-body { .note-body {
@include md-typography; @include md-typography;
margin-left: 45px; margin-left: 45px;
.highlight {
@include border-radius(4px);
}
} }
.note-header { .note-header {
padding-bottom: 5px; padding-bottom: 5px;
......
...@@ -8,7 +8,7 @@ module Issues ...@@ -8,7 +8,7 @@ module Issues
@issues = case params[:status] @issues = case params[:status]
when issues_filter[:all] then @project.issues when issues_filter[:all] then @project.issues
when issues_filter[:closed] then @project.issues.closed when issues_filter[:closed] then @project.issues.closed
when issues_filter[:to_me] then @project.issues.assigned(current_user) when issues_filter[:to_me] then @project.issues.assigned_to(current_user)
when issues_filter[:by_me] then @project.issues.authored(current_user) when issues_filter[:by_me] then @project.issues.authored(current_user)
else @project.issues.opened else @project.issues.opened
end end
......
...@@ -51,6 +51,7 @@ module Projects ...@@ -51,6 +51,7 @@ module Projects
if shell.import_repository(@project.path_with_namespace, @project.import_url) if shell.import_repository(@project.path_with_namespace, @project.import_url)
# We should create satellite for imported repo # We should create satellite for imported repo
@project.satellite.create unless @project.satellite.exists? @project.satellite.create unless @project.satellite.exists?
@project.imported = true
true true
else else
@project.errors.add(:import_url, 'cannot clone repo') @project.errors.add(:import_url, 'cannot clone repo')
......
...@@ -8,10 +8,6 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -8,10 +8,6 @@ class Admin::GroupsController < Admin::ApplicationController
end end
def show def show
@projects = Project.scoped
@projects = @projects.not_in_group(@group) if @group.projects.present?
@projects = @projects.all
@projects.reject!(&:empty_repo?)
end end
def new def new
......
...@@ -55,8 +55,14 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -55,8 +55,14 @@ class Admin::UsersController < Admin::ApplicationController
def create def create
admin = params[:user].delete("admin") admin = params[:user].delete("admin")
@admin_user = User.new(params[:user], as: :admin) opts = {
force_random_password: true,
password_expires_at: Time.now
}
@admin_user = User.new(params[:user].merge(opts), as: :admin)
@admin_user.admin = (admin && admin.to_i > 0) @admin_user.admin = (admin && admin.to_i > 0)
@admin_user.created_by_id = current_user.id
respond_to do |format| respond_to do |format|
if @admin_user.save if @admin_user.save
......
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :reject_blocked! before_filter :reject_blocked!
before_filter :check_password_expiration
before_filter :set_current_user_for_thread before_filter :set_current_user_for_thread
before_filter :add_abilities before_filter :add_abilities
before_filter :dev_tools if Rails.env == 'development' before_filter :dev_tools if Rails.env == 'development'
...@@ -156,4 +157,10 @@ class ApplicationController < ActionController::Base ...@@ -156,4 +157,10 @@ class ApplicationController < ActionController::Base
gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url gon.gravatar_url = request.ssl? || Gitlab.config.gitlab.https ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
end end
def check_password_expiration
if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now
redirect_to new_profile_password_path and return
end
end
end end
class PasswordsController < ApplicationController
layout 'navless'
skip_before_filter :check_password_expiration
before_filter :set_user
before_filter :set_title
def new
end
def create
new_password = params[:user][:password]
new_password_confirmation = params[:user][:password_confirmation]
result = @user.update_attributes(
password: new_password,
password_confirmation: new_password_confirmation
)
if result
@user.update_attributes(password_expires_at: nil)
redirect_to root_path, notice: 'Password successfully changed'
else
render :new
end
end
private
def set_user
@user = current_user
end
def set_title
@title = "New password"
end
end
...@@ -7,8 +7,12 @@ class SnippetsController < ApplicationController ...@@ -7,8 +7,12 @@ class SnippetsController < ApplicationController
# Allow destroy snippet # Allow destroy snippet
before_filter :authorize_admin_snippet!, only: [:destroy] before_filter :authorize_admin_snippet!, only: [:destroy]
before_filter :set_title
respond_to :html respond_to :html
layout 'navless'
def index def index
@snippets = Snippet.public.fresh.non_expired.page(params[:page]).per(20) @snippets = Snippet.public.fresh.non_expired.page(params[:page]).per(20)
end end
...@@ -98,4 +102,8 @@ class SnippetsController < ApplicationController ...@@ -98,4 +102,8 @@ class SnippetsController < ApplicationController
def authorize_admin_snippet! def authorize_admin_snippet!
return render_404 unless can?(current_user, :admin_personal_snippet, @snippet) return render_404 unless can?(current_user, :admin_personal_snippet, @snippet)
end end
def set_title
@title = 'Snippets'
end
end end
...@@ -142,7 +142,7 @@ module ApplicationHelper ...@@ -142,7 +142,7 @@ module ApplicationHelper
end end
def user_color_scheme_class def user_color_scheme_class
COLOR_SCHEMES[current_user.try(:color_scheme_id)] COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
end end
# Define whenever show last push event # Define whenever show last push event
......
...@@ -48,4 +48,36 @@ module ProjectsHelper ...@@ -48,4 +48,36 @@ module ProjectsHelper
def remove_project_message(project) def remove_project_message(project)
"You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?" "You are going to remove #{project.name_with_namespace}.\n Removed project CANNOT be restored!\n Are you ABSOLUTELY sure?"
end end
def project_nav_tabs
@nav_tabs ||= get_project_nav_tabs(@project, current_user)
end
def project_nav_tab?(name)
project_nav_tabs.include? name
end
private
def get_project_nav_tabs(project, current_user)
nav_tabs = [:home]
if project.repo_exists? && can?(current_user, :download_code, project)
nav_tabs << [:files, :commits, :network, :graphs]
end
if project.repo_exists? && project.merge_requests_enabled
nav_tabs << :merge_requests
end
if can?(current_user, :admin_project, project)
nav_tabs << :settings
end
[:issues, :wiki, :wall, :snippets].each do |feature|
nav_tabs << feature if project.send :"#{feature}_enabled"
end
nav_tabs.flatten
end
end end
...@@ -22,8 +22,10 @@ module Issuable ...@@ -22,8 +22,10 @@ module Issuable
scope :closed, -> { with_state(:closed) } scope :closed, -> { with_state(:closed) }
scope :of_group, ->(group) { where(project_id: group.project_ids) } scope :of_group, ->(group) { where(project_id: group.project_ids) }
scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
scope :assigned, ->(u) { where(assignee_id: u.id)} scope :assigned_to, ->(u) { where(assignee_id: u.id)}
scope :recent, -> { order("created_at DESC") } scope :recent, -> { order("created_at DESC") }
scope :assigned, -> { where("assignee_id IS NOT NULL") }
scope :unassigned, -> { where("assignee_id IS NULL") }
delegate :name, delegate :name,
:email, :email,
......
...@@ -27,7 +27,7 @@ class Issue < ActiveRecord::Base ...@@ -27,7 +27,7 @@ class Issue < ActiveRecord::Base
scope :cared, ->(user) { where(assignee_id: user) } scope :cared, ->(user) { where(assignee_id: user) }
scope :authored, ->(user) { where(author_id: user) } scope :authored, ->(user) { where(author_id: user) }
scope :open_for, ->(user) { opened.assigned(user) } scope :open_for, ->(user) { opened.assigned_to(user) }
state_machine :state, initial: :opened do state_machine :state, initial: :opened do
event :close do event :close do
......
...@@ -91,6 +91,15 @@ class MergeRequest < ActiveRecord::Base ...@@ -91,6 +91,15 @@ class MergeRequest < ActiveRecord::Base
if target_branch == source_branch if target_branch == source_branch
errors.add :branch_conflict, "You can not use same branch for source and target branches" errors.add :branch_conflict, "You can not use same branch for source and target branches"
end end
if opened? || reopened?
similar_mrs = self.project.merge_requests.where(source_branch: source_branch, target_branch: target_branch).opened
similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id
if similar_mrs.any?
errors.add :base, "There is already an open merge request for this branches"
end
end
end end
def reload_code def reload_code
......
...@@ -27,6 +27,7 @@ class Namespace < ActiveRecord::Base ...@@ -27,6 +27,7 @@ class Namespace < ActiveRecord::Base
message: "only letters, digits, spaces & '_' '-' '.' allowed." } message: "only letters, digits, spaces & '_' '-' '.' allowed." }
validates :description, length: { within: 0..255 } validates :description, length: { within: 0..255 }
validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
......
...@@ -79,6 +79,7 @@ class Project < ActiveRecord::Base ...@@ -79,6 +79,7 @@ class Project < ActiveRecord::Base
format: { with: Gitlab::Regex.project_name_regex, format: { with: Gitlab::Regex.project_name_regex,
message: "only letters, digits, spaces & '_' '-' '.' allowed. Letter should be first" } message: "only letters, digits, spaces & '_' '-' '.' allowed. Letter should be first" }
validates :path, presence: true, length: { within: 0..255 }, validates :path, presence: true, length: { within: 0..255 },
exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :issues_enabled, :wall_enabled, :merge_requests_enabled, validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
...@@ -92,7 +93,7 @@ class Project < ActiveRecord::Base ...@@ -92,7 +93,7 @@ class Project < ActiveRecord::Base
format: { with: URI::regexp(%w(http https)), message: "should be a valid url" }, format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
if: :import? if: :import?
validate :check_limit, :repo_name validate :check_limit
# Scopes # Scopes
scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
...@@ -166,14 +167,6 @@ class Project < ActiveRecord::Base ...@@ -166,14 +167,6 @@ class Project < ActiveRecord::Base
errors[:base] << ("Can't check your ability to create project") errors[:base] << ("Can't check your ability to create project")
end end
def repo_name
denied_paths = %w(admin dashboard groups help profile projects search)
if denied_paths.include?(path)
errors.add(:path, "like #{path} is not allowed")
end
end
def to_param def to_param
if namespace if namespace
namespace.path + "/" + path namespace.path + "/" + path
...@@ -420,6 +413,10 @@ class Project < ActiveRecord::Base ...@@ -420,6 +413,10 @@ class Project < ActiveRecord::Base
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?) !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end end
def imported?
imported
end
def rename_repo def rename_repo
old_path_with_namespace = File.join(namespace_dir, path_was) old_path_with_namespace = File.join(namespace_dir, path_was)
new_path_with_namespace = File.join(namespace_dir, path) new_path_with_namespace = File.join(namespace_dir, path)
......
...@@ -42,8 +42,11 @@ class User < ActiveRecord::Base ...@@ -42,8 +42,11 @@ class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username, attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password, :skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, as: [:default, :admin] :extern_uid, :provider, :password_expires_at,
attr_accessible :projects_limit, :can_create_team, :can_create_group, as: :admin as: [:default, :admin]
attr_accessible :projects_limit, :can_create_team, :can_create_group,
as: :admin
attr_accessor :force_random_password attr_accessor :force_random_password
...@@ -104,6 +107,7 @@ class User < ActiveRecord::Base ...@@ -104,6 +107,7 @@ class User < ActiveRecord::Base
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
validates :username, presence: true, uniqueness: true, validates :username, presence: true, uniqueness: true,
exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.username_regex, format: { with: Gitlab::Regex.username_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
...@@ -363,4 +367,8 @@ class User < ActiveRecord::Base ...@@ -363,4 +367,8 @@ class User < ActiveRecord::Base
def accessible_deploy_keys def accessible_deploy_keys
DeployKey.in_projects(self.master_projects).uniq DeployKey.in_projects(self.master_projects).uniq
end end
def created_by
User.find_by_id(created_by_id) if created_by_id
end
end end
class ProjectObserver < BaseObserver class ProjectObserver < BaseObserver
def after_create(project) def after_create(project)
unless project.forked? return true if project.forked? || project.imported?
GitlabShellWorker.perform_async(
:add_repository, GitlabShellWorker.perform_async(
project.path_with_namespace :add_repository,
) project.path_with_namespace
)
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
end log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
end end
def after_update(project) def after_update(project)
......
%h3.page_title %h3.page_title
Team: #{@team.name} New members for
= link_to @team.name, admin_team_path(@team)
%fieldset team
%legend Members (#{@team.members.count}) %hr
= form_tag admin_team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do = form_tag admin_team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do
%table#members_list - if @team.errors.any?
%thead .alert.alert-error
%tr %span= @team.errors.full_messages.first
%th User name .clearfix
%th Default project access = label_tag :user_ids do
%th Team access Users to add
%th .input
- @team.members.each do |member| = select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_username), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
%tr.member .clearfix.group-description-holder
%td = label_tag :default_project_access do
= link_to [:admin, member] do Default permission in projects
= member.name .input
%small= "(#{member.email})" = select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
%td= @team.human_default_projects_access(member) .clearfix
%td= @team.admin?(member) ? "Admin" : "Member" = label_tag :group_admin do
%td Is team admin
%tr .input
%td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_username), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5' = check_box_tag :group_admin
%td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" } .clearfix.form-actions
%td = submit_tag 'Add users into team', class: "btn btn-primary", id: :add_members_to_team
%span= check_box_tag :group_admin = link_to 'Cancel', :back, class: "btn"
%span Admin?
%td= submit_tag 'Add', class: "btn btn-primary", id: :add_members_to_team
...@@ -24,19 +24,25 @@ ...@@ -24,19 +24,25 @@
= f.text_field :email, required: true, autocomplete: "off" = f.text_field :email, required: true, autocomplete: "off"
%span.help-inline * required %span.help-inline * required
%fieldset - if @admin_user.new_record?
%legend Password %fieldset
.clearfix %legend Password
= f.label :password .clearfix
.input= f.password_field :password, disabled: f.object.force_random_password = f.label :password
.clearfix .input
= f.label :password_confirmation %strong
.input= f.password_field :password_confirmation, disabled: f.object.force_random_password A temporary password will be generated and sent to user.
-if f.object.new_record? %br
User will be forced to change it after first sign in
- else
%fieldset
%legend Password
.clearfix
= f.label :password
.input= f.password_field :password, disabled: f.object.force_random_password
.clearfix .clearfix
= f.label :force_random_password do = f.label :password_confirmation
%span Generate random password .input= f.password_field :password_confirmation, disabled: f.object.force_random_password
.input= f.check_box :force_random_password, {}, true, nil
%fieldset %fieldset
%legend Access %legend Access
......
%h3.page_title
User:
= @admin_user.name
- if @admin_user.blocked?
%span.cred (Blocked)
- if @admin_user.admin
%span.cred (Admin)
.pull-right
= link_to edit_admin_user_path(@admin_user), class: "btn grouped btn-small" do
%i.icon-edit
Edit
- unless @admin_user == current_user
- if @admin_user.blocked?
= link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn grouped btn-small success"
- else
= link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn grouped btn-small btn-remove"
= link_to 'Destroy', [:admin, @admin_user], confirm: "USER #{@admin_user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn grouped btn-small btn-remove"
%hr
.row .row
.span6 .span6
%h3.page_title .ui-box
= image_tag gravatar_icon(@admin_user.email, 90), class: "avatar s90" %h5.title
= @admin_user.name Account:
- if @admin_user.blocked? .pull-right
%span.cred (Blocked) = image_tag gravatar_icon(@admin_user.email, 32), class: "avatar s32"
- if @admin_user.admin %ul.well-list
%span.cred (Admin) %li
.pull-right %span.light Name:
= link_to edit_admin_user_path(@admin_user), class: "btn pull-right" do %strong= @admin_user.name
%i.icon-edit %li
Edit %span.light Username:
%br %strong
%small @#{@admin_user.username} = @admin_user.username
%br %li
%small member since #{@admin_user.created_at.stamp("Nov 12, 2031")} %span.light Email:
.clearfix %strong
%hr = mail_to @admin_user.email
%p
%span.btn.btn-small %li
%i.icon-envelope %span.light Member since:
= mail_to @admin_user.email %strong
- unless @admin_user == current_user = @admin_user.created_at.stamp("Nov 12, 2031")
- if @admin_user.blocked?
= link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn btn-small success" %li
- else %span.light Last sign-in at:
= link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" %strong
= link_to 'Destroy', [:admin, @admin_user], confirm: "USER #{@admin_user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove" - if @admin_user.last_sign_in_at
= @admin_user.last_sign_in_at.stamp("Nov 12, 2031")
- else
never
- if @admin_user.ldap_user?
%li
%span.light LDAP uid:
%strong
= @admin_user.extern_uid
- if @admin_user.created_by
%li
%span.light Created by:
%strong
= link_to @admin_user.created_by.name, [:admin, @admin_user.created_by]
%hr %hr
%h5 %h5
Add User to Projects Add User to Projects
...@@ -67,11 +103,11 @@ ...@@ -67,11 +103,11 @@
.span6 .span6
= render 'users/profile', user: @admin_user
.ui-box .ui-box
%h5.title Projects (#{@projects.count}) %h5.title Projects (#{@projects.count})
%ul.well-list %ul.well-list
- @projects.sort_by(&:name_with_namespace).each do |project| - @projects.sort_by(&:name_with_namespace).each do |project|
- tm = project.team.get_tm(@admin_user.id)
%li %li
= link_to admin_project_path(project), class: dom_class(project) do = link_to admin_project_path(project), class: dom_class(project) do
- if project.namespace - if project.namespace
...@@ -79,16 +115,17 @@ ...@@ -79,16 +115,17 @@
\/ \/
%strong.well-title %strong.well-title
= truncate(project.name, length: 45) = truncate(project.name, length: 45)
%span.pull-right.light
- if project.owner == @admin_user - if project.owner == @admin_user
%i.icon-wrench %span.label.label-info owner
- tm = project.team.get_tm(@admin_user.id)
- if tm - if tm
= tm.project_access_human .pull-right
= link_to edit_admin_project_member_path(project, tm.user), class: "btn btn-small" do = link_to edit_admin_project_member_path(project, tm.user), class: "btn grouped btn-small" do
%i.icon-edit %i.icon-edit
= link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @admin_user), method: :delete, class: "btn btn-small btn-remove" do = link_to admin_project_member_path(project, tm.user), confirm: remove_from_project_team_message(project, @admin_user), method: :delete, class: "btn grouped btn-small btn-remove" do
%i.icon-remove %i.icon-remove
%p.light
%i.icon-wrench .pull-right.light
&ndash; user is a project owner = tm.project_access_human
&nbsp;
- if enabled_oauth_providers.present? - providers = (enabled_oauth_providers - [:ldap])
- if providers.present?
%hr %hr
%div{:'data-no-turbolink' => 'data-no-turbolink'} %div{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp; %span Sign in with: &nbsp;
- (enabled_oauth_providers - [:ldap]).each do |provider| - providers.each do |provider|
%span %span
- if default_providers.include?(provider) - if default_providers.include?(provider)
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider) = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
= hidden_field_tag 'last_commit', @last_commit = hidden_field_tag 'last_commit', @last_commit
= hidden_field_tag 'content', '', id: :file_content = hidden_field_tag 'content', '', id: :file_content
.commit-button-annotation .commit-button-annotation
= button_tag "Commit", class: 'btn commit-btn js-commit-button' = button_tag "Commit changes", class: 'btn commit-btn js-commit-button btn-primary'
.message .message
to branch to branch
%strong= @ref %strong= @ref
......
...@@ -3,43 +3,48 @@ ...@@ -3,43 +3,48 @@
= link_to project_path(@project), title: "Project" do = link_to project_path(@project), title: "Project" do
%i.icon-home %i.icon-home
- unless @project.empty_repo? - if project_nav_tab? :files
- if can? current_user, :download_code, @project = nav_link(controller: %w(tree blob blame)) do
= nav_link(controller: %w(tree blob blame)) do = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
= link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
= nav_link(controller: %w(commit commits compare repositories protected_branches)) do - if project_nav_tab? :commits
= link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) = nav_link(controller: %w(commit commits compare repositories protected_branches)) do
= nav_link(controller: %w(network)) do = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref)
= link_to "Network", project_network_path(@project, @ref || @repository.root_ref)
= nav_link(controller: %w(graphs)) do - if project_nav_tab? :network
= link_to "Graphs", project_graph_path(@project, @ref || @repository.root_ref) = nav_link(controller: %w(network)) do
= link_to "Network", project_network_path(@project, @ref || @repository.root_ref)
- if @project.issues_enabled
- if project_nav_tab? :graphs
= nav_link(controller: %w(graphs)) do
= link_to "Graphs", project_graph_path(@project, @ref || @repository.root_ref)
- if project_nav_tab? :issues
= nav_link(controller: %w(issues milestones labels)) do = nav_link(controller: %w(issues milestones labels)) do
= link_to url_for_project_issues do = link_to url_for_project_issues do
Issues Issues
- if @project.used_default_issues_tracker? - if @project.used_default_issues_tracker?
%span.count.issue_counter= @project.issues.opened.count %span.count.issue_counter= @project.issues.opened.count
- if @project.repo_exists? && @project.merge_requests_enabled - if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do = nav_link(controller: :merge_requests) do
= link_to project_merge_requests_path(@project) do = link_to project_merge_requests_path(@project) do
Merge Requests Merge Requests
%span.count.merge_counter= @project.merge_requests.opened.count %span.count.merge_counter= @project.merge_requests.opened.count
- if @project.wiki_enabled - if project_nav_tab? :wiki
= nav_link(controller: :wikis) do = nav_link(controller: :wikis) do
= link_to 'Wiki', project_wiki_path(@project, :home) = link_to 'Wiki', project_wiki_path(@project, :home)
- if @project.wall_enabled - if project_nav_tab? :wall
= nav_link(controller: :walls) do = nav_link(controller: :walls) do
= link_to 'Wall', project_wall_path(@project) = link_to 'Wall', project_wall_path(@project)
- if @project.snippets_enabled - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to 'Snippets', project_snippets_path(@project) = link_to 'Snippets', project_snippets_path(@project)
- if can? current_user, :admin_project, @project - if project_nav_tab? :settings
= nav_link(html_options: {class: "#{project_tab_class}"}) do = nav_link(html_options: {class: "#{project_tab_class}"}) do
= link_to edit_project_path(@project), class: "stat-tab tab " do = link_to edit_project_path(@project), class: "stat-tab tab " do
Settings Settings
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
Members Members
%span.count= @team.members.count %span.count= @team.members.count
- if can? current_user, :admin_user_team, @team - if can? current_user, :manage_user_team, @team
= nav_link(path: 'teams#edit') do = nav_link(path: 'teams#edit') do
= link_to edit_team_path(@team), class: "stat-tab tab " do = link_to edit_team_path(@team), class: "stat-tab tab " do
Settings Settings
......
!!! 5
%html{ lang: "en"}
= render "layouts/head", title: "Snipepts"
%body{class: "#{app_theme} application", :'data-page' => body_data_page}
= render "layouts/head_panel", title: "Snippets"
= render "layouts/flash"
%nav.main-nav
.container
%ul
= nav_link(path: 'snippets#user_index', html_options: {class: 'home'}) do
= link_to user_snippets_path(current_user), title: "My Snippets" do
%i.icon-home
= nav_link(path: 'snippets#new') do
= link_to new_snippet_path do
New snippet
= nav_link(path: 'snippets#index') do
= link_to snippets_path do
Discover snippets
.container
.content= yield
.ui-box
%h5.title= title
%ul.well-list
- issues.each do |issue|
%li
= link_to [@project, issue] do
%span.badge{class: issue.closed? ? 'badge-important' : 'badge-info'} ##{issue.id}
= link_to_gfm truncate(issue.title, length: 60), [@project, issue]
- if issue.assignee
.pull-right
= image_tag gravatar_icon(issue.assignee.email, 16), class: "avatar s16"
%li
= link_to [@project, merge_request] do
%span.badge.badge-info ##{merge_request.id}
&ndash;
= link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request]
...@@ -55,39 +55,52 @@ ...@@ -55,39 +55,52 @@
= markdown @milestone.description = markdown @milestone.description
.row %ul.nav.nav-tabs
.span6 %li.active
.ui-box.milestone-issue-filter = link_to '#tab-issues', 'data-toggle' => 'tab' do
.title Issues
%ul.nav.nav-pills %span.badge= @issues.count
%li.active= link_to('Open Issues', '#') %li
%li=link_to('All Issues', '#') = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
%ul.well-list Merge Requests
- @issues.each do |issue| %span.badge= @merge_requests.count
%li{data: {closed: issue.closed?}} %li
= link_to [@project, issue] do = link_to '#tab-participants', 'data-toggle' => 'tab' do
%span.badge.badge-info ##{issue.id} Participants
&ndash; %span.badge= @users.count
= link_to_gfm truncate(issue.title, length: 60), [@project, issue]
.span6
.ui-box.milestone-merge-requests-filter
.title
%ul.nav.nav-pills
%li.active= link_to('Open Merge Requests', '#')
%li=link_to('All Merge Requests', '#')
%ul.well-list
- @merge_requests.each do |merge_request|
%li{data: {closed: merge_request.closed? || merge_request.merged?}}
= link_to [@project, merge_request] do
%span.badge.badge-info ##{merge_request.id}
&ndash;
= link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request]
%hr .tab-content
%h6 Participants: .tab-pane.active#tab-issues
%div .row
- @users.each do |user| .span4
= link_to_member(@project, user) = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.opened.unassigned)
.span4
= render('issues', title: 'Ongoing Issues (open and assigned)', issues: @issues.opened.assigned)
.span4
= render('issues', title: 'Completed Issues (closed)', issues: @issues.closed)
.tab-pane#tab-merge-requests
.row
.span6
.ui-box
%h5.title Open
%ul.well-list
- @merge_requests.opened.each do |merge_request|
= render 'merge_request', merge_request: merge_request
.span6
.ui-box
%h5.title Closed
%ul.well-list
- @merge_requests.closed.each do |merge_request|
= render 'merge_request', merge_request: merge_request
.clearfix .tab-pane#tab-participants
%ul.bordered-list
- @users.each do |user|
%li
= link_to user, title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 32), class: "avatar s32"
%strong= truncate(user.name, lenght: 40)
%br
%small.cgray= user.username
...@@ -8,13 +8,14 @@ ...@@ -8,13 +8,14 @@
%p %p
login.......................................... login..........................................
%code= @user['email'] %code= @user['email']
%p
- unless Gitlab.config.gitlab.signup_enabled - if @user.created_by_id
%p
password.................................. password..................................
%code= @password %code= @password
%p %p
Please change your password immediately after login. You will be forced to change this password immediately after login.
%p %p
= link_to "Click here to login", root_url = link_to "Click here to login", root_url
...@@ -3,10 +3,11 @@ Hi <%= @user.name %>! ...@@ -3,10 +3,11 @@ Hi <%= @user.name %>!
The Administrator created an account for you. Now you are a member of company GitLab application. The Administrator created an account for you. Now you are a member of company GitLab application.
login.................. <%= @user.email %> login.................. <%= @user.email %>
<% unless Gitlab.config.gitlab.signup_enabled %> <% if @user.created_by_id %>
password............... <%= @password %> password............... <%= @password %>
You will be forced to change this password immediately after login.
<% end %> <% end %>
Please change your password immediately after login.
Click here to login: <%= url_for(root_url) %> Click here to login: <%= url_for(root_url) %>
= form_for @user, url: profile_password_path, method: :post do |f|
.light-well.padded
%p.slead
Please set new password before proceed.
%br
After successful password update you will be redirected to login screen
-if @user.errors.any?
.alert.alert-error
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
.clearfix
= f.label :password
.input= f.password_field :password, required: true
.clearfix
= f.label :password_confirmation
.input
= f.password_field :password_confirmation, required: true
.clearfix
.input
= f.submit 'Set new password', class: "btn btn-create"
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
Edit Edit
= nav_link(controller: [:team_members, :teams]) do = nav_link(controller: [:team_members, :teams]) do
= link_to project_team_index_path(@project), class: "team-tab tab" do = link_to project_team_index_path(@project), class: "team-tab tab" do
%i.icon-user %i.icon-group
Team Project Members
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= link_to project_deploy_keys_path(@project) do = link_to project_deploy_keys_path(@project) do
%span %span
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
= nav_link(controller: :hooks) do = nav_link(controller: :hooks) do
= link_to project_hooks_path(@project) do = link_to project_hooks_path(@project) do
%span %span
Hooks Web Hooks
= nav_link(controller: :services) do = nav_link(controller: :services) do
= link_to project_services_path(@project) do = link_to project_services_path(@project) do
%span %span
......
%h3.page_title %h3.page_title
My Snippets My Snippets
%small share code pastes with others out of git repository %small share code pastes with others out of git repository
= link_to new_snippet_path, class: "btn btn-small add_new pull-right", title: "New Snippet" do .pull-right
Add new snippet = link_to new_snippet_path, class: "btn btn-small add_new grouped btn-primary", title: "New Snippet" do
Add new snippet
= link_to snippets_path, class: "btn btn-small grouped" do
Discover snippets
%hr %hr
......
%h3.page_title %h3.page_title
Public snippets Public snippets
%small share code pastes with others out of git repository %small share code pastes with others out of git repository
= link_to new_snippet_path, class: "btn btn-small add_new pull-right", title: "New Snippet" do
Add new snippet .pull-right
= link_to new_snippet_path, class: "btn btn-small add_new grouped btn-primary", title: "New Snippet" do
Add new snippet
= link_to user_snippets_path(current_user), class: "btn btn-small grouped" do
My snippets
%hr %hr
.row .row
......
= render "projects/settings_nav" = render "projects/settings_nav"
%h3.page_title %h3.page_title
Team Members Project Members
(#{@project.users.count}) (#{@project.users.count})
%small %small
Read more about project permissions Read more about project permissions
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
= link_to 'Projects', '#tab-projects', 'data-toggle' => 'tab' = link_to 'Projects', '#tab-projects', 'data-toggle' => 'tab'
%li %li
= link_to 'Edit Team', '#tab-edit', 'data-toggle' => 'tab' = link_to 'Edit Team', '#tab-edit', 'data-toggle' => 'tab'
%li - if can? current_user, :admin_user_team, @team
= link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab' %li
= link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab'
.span9 .span9
.tab-content .tab-content
......
...@@ -52,7 +52,7 @@ Gitlab::Application.configure do ...@@ -52,7 +52,7 @@ Gitlab::Application.configure do
# config.action_mailer.raise_delivery_errors = false # config.action_mailer.raise_delivery_errors = false
# Enable threaded mode # Enable threaded mode
config.threadsafe! config.threadsafe! unless $rails_rake_task
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found) # the I18n.default_locale when a translation can not be found)
......
...@@ -123,6 +123,7 @@ Gitlab::Application.routes.draw do ...@@ -123,6 +123,7 @@ Gitlab::Application.routes.draw do
end end
resource :notifications resource :notifications
resource :password
end end
resources :keys resources :keys
......
...@@ -3,7 +3,8 @@ admin = User.create( ...@@ -3,7 +3,8 @@ admin = User.create(
name: "Administrator", name: "Administrator",
username: 'root', username: 'root',
password: "5iveL!fe", password: "5iveL!fe",
password_confirmation: "5iveL!fe" password_confirmation: "5iveL!fe",
password_expires_at: Time.now
) )
admin.projects_limit = 10000 admin.projects_limit = 10000
......
class AddPasswordExpiresAtToUsers < ActiveRecord::Migration
def change
add_column :users, :password_expires_at, :datetime
end
end
class AddCreatedByIdToUser < ActiveRecord::Migration
def change
add_column :users, :created_by_id, :integer
end
end
class AddImprotedToProject < ActiveRecord::Migration
def change
add_column :projects, :imported, :boolean, default: false, null: false
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130522141856) do ActiveRecord::Schema.define(:version => 20130614132337) do
create_table "deploy_keys_projects", :force => true do |t| create_table "deploy_keys_projects", :force => true do |t|
t.integer "deploy_key_id", :null => false t.integer "deploy_key_id", :null => false
...@@ -172,6 +172,7 @@ ActiveRecord::Schema.define(:version => 20130522141856) do ...@@ -172,6 +172,7 @@ ActiveRecord::Schema.define(:version => 20130522141856) do
t.string "issues_tracker_id" t.string "issues_tracker_id"
t.boolean "snippets_enabled", :default => true, :null => false t.boolean "snippets_enabled", :default => true, :null => false
t.datetime "last_activity_at" t.datetime "last_activity_at"
t.boolean "imported", :default => false, :null => false
end end
add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id" add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"
...@@ -292,6 +293,8 @@ ActiveRecord::Schema.define(:version => 20130522141856) do ...@@ -292,6 +293,8 @@ ActiveRecord::Schema.define(:version => 20130522141856) do
t.string "state" t.string "state"
t.integer "color_scheme_id", :default => 1, :null => false t.integer "color_scheme_id", :default => 1, :null => false
t.integer "notification_level", :default => 1, :null => false t.integer "notification_level", :default => 1, :null => false
t.datetime "password_expires_at"
t.integer "created_by_id"
end end
add_index "users", ["admin"], :name => "index_users_on_admin" add_index "users", ["admin"], :name => "index_users_on_admin"
......
...@@ -69,15 +69,15 @@ When listing resources you can pass the following parameters: ...@@ -69,15 +69,15 @@ When listing resources you can pass the following parameters:
## Contents ## Contents
+ [Users](doc/api/users.md) + [Users](users.md)
+ [Session](doc/api/session.md) + [Session](session.md)
+ [Projects](doc/api/projects.md) + [Projects](projects.md)
+ [Project Snippets](doc/api/project_snippets.md) + [Project Snippets](project_snippets.md)
+ [Repositories](doc/api/repositories.md) + [Repositories](repositories.md)
+ [Issues](doc/api/issues.md) + [Issues](issues.md)
+ [Milestones](doc/api/milestones.md) + [Milestones](milestones.md)
+ [Notes](doc/api/notes.md) + [Notes](notes.md)
+ [Deploy Keys](doc/api/deploy_keys.md) + [Deploy Keys](deploy_keys.md)
+ [System Hooks](doc/api/system_hooks.md) + [System Hooks](system_hooks.md)
+ [Groups](doc/api/groups.md) + [Groups](groups.md)
+ [User Teams](doc/api/user_teams.md) + [User Teams](user_teams.md)
...@@ -148,10 +148,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install ...@@ -148,10 +148,10 @@ To setup the MySQL/PostgreSQL database and dependencies please see [`doc/install
cd /home/git/gitlab cd /home/git/gitlab
# Checkout to stable release # Checkout to stable release
sudo -u git -H git checkout 5-2-stable sudo -u git -H git checkout 5-3-stable
**Note:** **Note:**
You can change `5-2-stable` to `master` if you want the *bleeding edge* version, but do so with caution! You can change `5-3-stable` to `master` if you want the *bleeding edge* version, but do so with caution!
## Configure it ## Configure it
...@@ -352,10 +352,10 @@ GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already ...@@ -352,10 +352,10 @@ GitLab uses [Omniauth](http://www.omniauth.org/) for authentication and already
These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation. These steps are fairly general and you will need to figure out the exact details from the Omniauth provider's documentation.
* Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/Gemfile#L18) * Add `gem "omniauth-your-auth-provider"` to the [Gemfile](https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/Gemfile#L18)
* Run `sudo -u git -H bundle install` to install the new gem(s) * Run `sudo -u git -H bundle install` to install the new gem(s)
* Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/gitlab.yml.example#L53) as a reference) * Add provider specific configuration options to your `config/gitlab.yml` (you can use the [auth providers section of the example config](https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example#L53) as a reference)
* Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/5-2-stable/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons) * Add icons for the new provider into the [vendor/assets/images/authbuttons](https://github.com/gitlabhq/gitlabhq/tree/5-3-stable/vendor/assets/images/authbuttons) directory (you can find some more popular ones over at https://github.com/intridea/authbuttons)
* Restart GitLab * Restart GitLab
### Examples ### Examples
......
# From 5.2 to 5.3
### 0. Backup
It's useful to make a backup just in case things go south:
(With MySQL, this may require granting "LOCK TABLES" privileges to the GitLab user on the database version)
```bash
cd /home/git/gitlab
sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:create
```
### 1. Stop server
sudo service gitlab stop
### 2. Get latest code
```bash
cd /home/git/gitlab
sudo -u git -H git fetch
sudo -u git -H git checkout 5-3-stable
```
### 3. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
#PostgreSQL
sudo -u git -H bundle install --without development test mysql --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
```
### 4. Update config files
* Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-2-stable/config/puma.rb.example but with your settings.
### 5. Update Init script
```bash
sudo rm /etc/init.d/gitlab
sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5-3-stable/lib/support/init.d/gitlab
sudo chmod +x /etc/init.d/gitlab
```
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade complete!
## Things went south? Revert to previous version (5.2)
### 1. Revert the code to the previous version
Follow the [`upgrade guide from 5.1 to 5.2`](5.1-to-5.2.md), except for the database migration
(The backup is already migrated to the previous version)
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H RAILS_ENV=production bundle exec rake gitlab:backup:restore
```
...@@ -22,5 +22,3 @@ Feature: Project Milestones ...@@ -22,5 +22,3 @@ Feature: Project Milestones
Given the milestone has open and closed issues Given the milestone has open and closed issues
And I click link "v2.2" And I click link "v2.2"
Then I should see 3 issues Then I should see 3 issues
When I click link "All Issues"
Then I should see 4 issues
...@@ -45,7 +45,7 @@ class ProjectActiveTab < Spinach::FeatureSteps ...@@ -45,7 +45,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Home # Sub Tabs: Home
Given 'I click the "Team" tab' do Given 'I click the "Team" tab' do
click_link('Team') click_link('Project Members')
end end
Given 'I click the "Attachments" tab' do Given 'I click the "Attachments" tab' do
...@@ -61,7 +61,7 @@ class ProjectActiveTab < Spinach::FeatureSteps ...@@ -61,7 +61,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
end end
Given 'I click the "Hooks" tab' do Given 'I click the "Hooks" tab' do
click_link('Hooks') click_link('Web Hooks')
end end
Given 'I click the "Deploy Keys" tab' do Given 'I click the "Deploy Keys" tab' do
...@@ -73,7 +73,7 @@ class ProjectActiveTab < Spinach::FeatureSteps ...@@ -73,7 +73,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
end end
Then 'the active sub tab should be Team' do Then 'the active sub tab should be Team' do
ensure_active_sub_tab('Team') ensure_active_sub_tab('Project Members')
end end
Then 'the active sub tab should be Attachments' do Then 'the active sub tab should be Attachments' do
...@@ -89,7 +89,7 @@ class ProjectActiveTab < Spinach::FeatureSteps ...@@ -89,7 +89,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
end end
Then 'the active sub tab should be Hooks' do Then 'the active sub tab should be Hooks' do
ensure_active_sub_tab('Hooks') ensure_active_sub_tab('Web Hooks')
end end
Then 'the active sub tab should be Deploy Keys' do Then 'the active sub tab should be Deploy Keys' do
......
...@@ -57,8 +57,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps ...@@ -57,8 +57,8 @@ class ProjectMergeRequests < Spinach::FeatureSteps
And 'I submit new merge request "Wiki Feature"' do And 'I submit new merge request "Wiki Feature"' do
fill_in "merge_request_title", with: "Wiki Feature" fill_in "merge_request_title", with: "Wiki Feature"
select "master", from: "merge_request_source_branch" select "bootstrap", from: "merge_request_source_branch"
select "stable", from: "merge_request_target_branch" select "master", from: "merge_request_target_branch"
click_button "Submit merge request" click_button "Submit merge request"
end end
......
...@@ -50,12 +50,6 @@ class ProjectMilestones < Spinach::FeatureSteps ...@@ -50,12 +50,6 @@ class ProjectMilestones < Spinach::FeatureSteps
end end
Then "I should see 3 issues" do Then "I should see 3 issues" do
page.should have_selector('.milestone-issue-filter .well-list li', count: 4) page.should have_selector('#tab-issues li', count: 4)
page.should have_selector('.milestone-issue-filter .well-list li.hide', count: 1)
end
Then "I should see 4 issues" do
page.should have_selector('.milestone-issue-filter .well-list li', count: 4)
page.should_not have_selector('.milestone-issue-filter .well-list li.hide')
end end
end end
...@@ -93,7 +93,7 @@ class Userteams < Spinach::FeatureSteps ...@@ -93,7 +93,7 @@ class Userteams < Spinach::FeatureSteps
Then 'I should see issues from this team assigned to me' do Then 'I should see issues from this team assigned to me' do
team = UserTeam.last team = UserTeam.last
team.projects.each do |project| team.projects.each do |project|
project.issues.assigned(current_user).each do |issue| project.issues.assigned_to(current_user).each do |issue|
page.should have_content issue.title page.should have_content issue.title
end end
end end
...@@ -121,7 +121,7 @@ class Userteams < Spinach::FeatureSteps ...@@ -121,7 +121,7 @@ class Userteams < Spinach::FeatureSteps
team = UserTeam.last team = UserTeam.last
team.projects.each do |project| team.projects.each do |project|
team.members.each do |member| team.members.each do |member|
project.issues.assigned(member).each do |issue| project.issues.assigned_to(member).each do |issue|
page.should have_content issue.title page.should have_content issue.title
end end
end end
...@@ -131,9 +131,7 @@ class Userteams < Spinach::FeatureSteps ...@@ -131,9 +131,7 @@ class Userteams < Spinach::FeatureSteps
Given 'project from team has merge requests assigned to me' do Given 'project from team has merge requests assigned to me' do
team = UserTeam.last team = UserTeam.last
team.projects.each do |project| team.projects.each do |project|
team.members.each do |member| create(:merge_request, assignee: current_user, project: project)
3.times { create(:merge_request, assignee: member, project: project) }
end
end end
end end
...@@ -145,10 +143,8 @@ class Userteams < Spinach::FeatureSteps ...@@ -145,10 +143,8 @@ class Userteams < Spinach::FeatureSteps
Then 'I should see merge requests from this team assigned to me' do Then 'I should see merge requests from this team assigned to me' do
team = UserTeam.last team = UserTeam.last
team.projects.each do |project| team.projects.each do |project|
team.members.each do |member| project.merge_requests.each do |merge_request|
project.issues.assigned(member).each do |merge_request| page.should have_content merge_request.title
page.should have_content merge_request.title
end
end end
end end
end end
...@@ -156,20 +152,8 @@ class Userteams < Spinach::FeatureSteps ...@@ -156,20 +152,8 @@ class Userteams < Spinach::FeatureSteps
Given 'project from team has merge requests assigned to team members' do Given 'project from team has merge requests assigned to team members' do
team = UserTeam.last team = UserTeam.last
team.projects.each do |project| team.projects.each do |project|
team.members.each do |member| member = team.members.sample
3.times { create(:merge_request, assignee: member, project: project) } create(:merge_request, assignee: member, project: project)
end
end
end
Then 'I should see merge requests from this team assigned to me' do
team = UserTeam.last
team.projects.each do |project|
team.members.each do |member|
project.issues.assigned(member).each do |merge_request|
page.should have_content merge_request.title
end
end
end end
end end
......
require_relative 'shell_env' require_relative 'shell_env'
require 'omniauth-ldap' require_relative 'grack_ldap'
require_relative 'grack_helpers'
module Grack module Grack
class Auth < Rack::Auth::Basic class Auth < Rack::Auth::Basic
attr_accessor :user, :project include LDAP
include Helpers
attr_accessor :user, :project, :ref, :env
def call(env) def call(env)
@env = env @env = env
...@@ -14,42 +18,52 @@ module Grack ...@@ -14,42 +18,52 @@ module Grack
@env['PATH_INFO'] = @request.path @env['PATH_INFO'] = @request.path
@env['SCRIPT_NAME'] = "" @env['SCRIPT_NAME'] = ""
return render_not_found unless project auth!
return unauthorized unless project.public || @auth.provided?
return bad_request if @auth.provided? && !@auth.basic?
if valid?
if @auth.provided?
@env['REMOTE_USER'] = @auth.username
end
return @app.call(env)
else
unauthorized
end
end end
def valid? private
def auth!
return render_not_found unless project
if @auth.provided? if @auth.provided?
return bad_request unless @auth.basic?
# Authentication with username and password # Authentication with username and password
login, password = @auth.credentials login, password = @auth.credentials
@user = authenticate(login, password) @user = authenticate_user(login, password)
return false unless @user
Gitlab::ShellEnv.set_env(@user) if @user
Gitlab::ShellEnv.set_env(@user)
@env['REMOTE_USER'] = @auth.username
else
return unauthorized
end
else
return unauthorized unless project.public
end end
if authorized_git_request?
@app.call(env)
else
unauthorized
end
end
def authorized_git_request?
# Git upload and receive # Git upload and receive
if @request.get? if @request.get?
validate_get_request authorize_request(@request.params['service'])
elsif @request.post? elsif @request.post?
validate_post_request authorize_request(File.basename(@request.path))
else else
false false
end end
end end
def authenticate(login, password) def authenticate_user(login, password)
user = User.find_by_email(login) || User.find_by_username(login) user = User.find_by_email(login) || User.find_by_username(login)
# If the provided login was not a known email or username # If the provided login was not a known email or username
...@@ -65,34 +79,12 @@ module Grack ...@@ -65,34 +79,12 @@ module Grack
end end
end end
def ldap_auth(login, password) def authorize_request(service)
# Check user against LDAP backend if user is not authenticated case service
# Only check with valid login and password to prevent anonymous bind results when 'git-upload-pack'
return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
ldap_user = ldap.bind_as(
filter: Net::LDAP::Filter.eq(ldap.uid, login),
size: 1,
password: password
)
User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
end
def validate_get_request
validate_request(@request.params['service'])
end
def validate_post_request
validate_request(File.basename(@request.path))
end
def validate_request(service)
if service == 'git-upload-pack'
project.public || can?(user, :download_code, project) project.public || can?(user, :download_code, project)
elsif service == 'git-receive-pack' when'git-receive-pack'
action = if project.protected_branch?(current_ref) action = if project.protected_branch?(ref)
:push_code_to_protected_branches :push_code_to_protected_branches
else else
:push_code :push_code
...@@ -104,49 +96,24 @@ module Grack ...@@ -104,49 +96,24 @@ module Grack
end end
end end
def can?(object, action, subject)
abilities.allowed?(object, action, subject)
end
def current_ref
if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
input = Zlib::GzipReader.new(@request.body).read
else
input = @request.body.read
end
# Need to reset seek point
@request.body.rewind
/refs\/heads\/([\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
end
def project def project
unless instance_variable_defined? :@project @project ||= project_by_path(@request.path_info)
# Find project by PATH_INFO from env
if m = /^\/([\w\.\/-]+)\.git/.match(@request.path_info).to_a
@project = Project.find_with_namespace(m.last)
end
end
return @project
end end
PLAIN_TYPE = {"Content-Type" => "text/plain"} def ref
@ref ||= parse_ref
def render_not_found
[404, PLAIN_TYPE, ["Not Found"]]
end end
protected def parse_ref
input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
Zlib::GzipReader.new(@request.body).read
else
@request.body.read
end
def abilities # Need to reset seek point
@abilities ||= begin @request.body.rewind
abilities = Six.new /refs\/heads\/([\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
abilities << Ability
abilities
end
end
def ldap_conf
@ldap_conf ||= Gitlab.config.ldap
end end
end# Auth end
end# Grack end
module Grack
module Helpers
def project_by_path(path)
if m = /^\/([\w\.\/-]+)\.git/.match(path).to_a
path_with_namespace = m.last
path_with_namespace.gsub!(/.wiki$/, '')
Project.find_with_namespace(path_with_namespace)
end
end
def render_not_found
[404, {"Content-Type" => "text/plain"}, ["Not Found"]]
end
def can?(object, action, subject)
abilities.allowed?(object, action, subject)
end
def abilities
@abilities ||= begin
abilities = Six.new
abilities << Ability
abilities
end
end
end
end
require 'omniauth-ldap'
module Grack
module LDAP
def ldap_auth(login, password)
# Check user against LDAP backend if user is not authenticated
# Only check with valid login and password to prevent anonymous bind results
return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
ldap_user = ldap.bind_as(
filter: Net::LDAP::Filter.eq(ldap.uid, login),
size: 1,
password: password
)
User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
end
def ldap_conf
@ldap_conf ||= Gitlab.config.ldap
end
end
end
module Gitlab
module Blacklist
extend self
def path
%w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets )
end
end
end
...@@ -20,13 +20,10 @@ describe "Admin::Users" do ...@@ -20,13 +20,10 @@ describe "Admin::Users" do
describe "GET /admin/users/new" do describe "GET /admin/users/new" do
before do before do
@password = "123ABC"
visit new_admin_user_path visit new_admin_user_path
fill_in "user_name", with: "Big Bang" fill_in "user_name", with: "Big Bang"
fill_in "user_username", with: "bang" fill_in "user_username", with: "bang"
fill_in "user_email", with: "bigbang@mail.com" fill_in "user_email", with: "bigbang@mail.com"
fill_in "user_password", with: @password
fill_in "user_password_confirmation", with: @password
end end
it "should create new user" do it "should create new user" do
...@@ -57,26 +54,13 @@ describe "Admin::Users" do ...@@ -57,26 +54,13 @@ describe "Admin::Users" do
end end
it "should send valid email to user with email & password" do it "should send valid email to user with email & password" do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(false)
User.observers.enable :user_observer do User.observers.enable :user_observer do
click_button "Create user" click_button "Create user"
user = User.last user = User.last
email = ActionMailer::Base.deliveries.last email = ActionMailer::Base.deliveries.last
email.subject.should have_content("Account was created") email.subject.should have_content("Account was created")
email.text_part.body.should have_content(user.email) email.text_part.body.should have_content(user.email)
email.text_part.body.should have_content(@password) email.text_part.body.should have_content('password')
end
end
it "should send valid email to user with email without password when signup is enabled" do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
User.observers.enable :user_observer do
click_button "Create user"
user = User.last
email = ActionMailer::Base.deliveries.last
email.subject.should have_content("Account was created")
email.text_part.body.should have_content(user.email)
email.text_part.body.should_not have_content(@password)
end end
end end
end end
......
...@@ -15,7 +15,7 @@ describe Notify do ...@@ -15,7 +15,7 @@ describe Notify do
describe 'for new users, the email' do describe 'for new users, the email' do
let(:example_site_path) { root_path } let(:example_site_path) { root_path }
let(:new_user) { create(:user, email: 'newguy@example.com') } let(:new_user) { create(:user, email: 'newguy@example.com', created_by_id: 1) }
subject { Notify.new_user_email(new_user.id, new_user.password) } subject { Notify.new_user_email(new_user.id, new_user.password) }
...@@ -32,8 +32,7 @@ describe Notify do ...@@ -32,8 +32,7 @@ describe Notify do
end end
it 'contains the new user\'s password' do it 'contains the new user\'s password' do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) should have_body_text /password/
should have_body_text /#{new_user.password}/
end end
it 'includes a link to the site' do it 'includes a link to the site' do
...@@ -61,8 +60,7 @@ describe Notify do ...@@ -61,8 +60,7 @@ describe Notify do
end end
it 'should not contain the new user\'s password' do it 'should not contain the new user\'s password' do
Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) should_not have_body_text /password/
should_not have_body_text /#{new_user.password}/
end end
it 'includes a link to the site' do it 'includes a link to the site' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment