Commit b4523ebb authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce-to-ee'

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	app/views/profiles/accounts/show.html.haml
parents 00c3c4c5 a209e62e
Please view this file on the master branch, on stable branches it's out of date.
v 7.13.0 (unreleased)
- Support commenting on diffs in side-by-side mode (Stan Hu)
- Fix JavaScript error when clicking on the comment button on a diff line that has a comment already (Stan Hu)
- Remove project visibility icons from dashboard projects list
- Rename "Design" profile settings page to "Preferences".
- Allow users to customize their default Dashboard page.
- Update ssl_ciphers in Nginx example to remove DHE settings. This will deny forward secrecy for Android 2.3.7, Java 6 and OpenSSL 0.9.8
v 7.12.0 (unreleased)
- Fix post-receive errors on a push when an external issue tracker is configured (Stan Hu)
- Update oauth button logos for Twitter and Google to recommended assets
- Fix hooks for web based events with external issue references (Daniel Gerhardt)
- Update browser gem to version 0.8.0 for IE11 support (Stan Hu)
- Fix timeout when rendering file with thousands of lines.
- Add "Remember me" checkbox to LDAP signin form.
- Add session expiration delay configuration through UI application settings
- Fix external issue tracker hook/test for HTTPS URLs (Daniel Gerhardt)
- Don't notify users mentioned in code blocks or blockquotes.
- Omit link to generate labels if user does not have access to create them (Stan Hu)
- Show warning when a comment will add 10 or more people to the discussion.
......
source "https://rubygems.org"
gem "rails", "~> 4.1.0"
gem 'rails', '4.1.11'
# Default values for AR models
gem "default_value_for", "~> 3.0.0"
......@@ -95,7 +95,7 @@ gem "seed-fu"
gem 'html-pipeline', '~> 1.11.0'
gem 'task_list', '1.0.2', require: 'task_list/railtie'
gem 'github-markup'
gem 'redcarpet', '~> 3.2.3'
gem 'redcarpet', '~> 3.3.0'
gem 'RedCloth'
gem 'rdoc', '~>3.6'
gem 'org-ruby', '= 0.9.12'
......@@ -194,7 +194,7 @@ gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.1'
gem 'gon', '~> 5.0.0'
gem 'jquery-atwho-rails', '~> 1.0.0'
gem 'jquery-rails', '3.1.2'
gem 'jquery-rails', '3.1.3'
gem 'jquery-scrollto-rails'
gem 'jquery-ui-rails'
gem 'nprogress-rails'
......
......@@ -4,31 +4,31 @@ GEM
CFPropertyList (2.3.1)
RedCloth (4.2.9)
ace-rails-ap (2.0.1)
actionmailer (4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
actionmailer (4.1.11)
actionpack (= 4.1.11)
actionview (= 4.1.11)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.9)
actionview (= 4.1.9)
activesupport (= 4.1.9)
actionpack (4.1.11)
actionview (= 4.1.11)
activesupport (= 4.1.11)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.9)
activesupport (= 4.1.9)
actionview (4.1.11)
activesupport (= 4.1.11)
builder (~> 3.1)
erubis (~> 2.7.0)
activemodel (4.1.9)
activesupport (= 4.1.9)
activemodel (4.1.11)
activesupport (= 4.1.11)
builder (~> 3.1)
activerecord (4.1.9)
activemodel (= 4.1.9)
activesupport (= 4.1.9)
activerecord (4.1.11)
activemodel (= 4.1.11)
activesupport (= 4.1.11)
arel (~> 5.0.0)
activeresource (4.0.0)
activemodel (~> 4.0)
activesupport (~> 4.0)
rails-observers (~> 0.1.1)
activesupport (4.1.9)
activesupport (4.1.11)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
......@@ -332,7 +332,7 @@ GEM
inflecto (0.0.2)
ipaddress (0.8.0)
jquery-atwho-rails (1.0.1)
jquery-rails (3.1.2)
jquery-rails (3.1.3)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
jquery-scrollto-rails (1.4.3)
......@@ -342,7 +342,7 @@ GEM
turbolinks
jquery-ui-rails (4.2.1)
railties (>= 3.2.16)
json (1.8.2)
json (1.8.3)
jwt (0.1.13)
multi_json (>= 1.5)
kaminari (0.15.1)
......@@ -367,7 +367,7 @@ GEM
mini_portile (0.6.2)
minitest (5.3.5)
mousetrap-rails (1.4.6)
multi_json (1.10.1)
multi_json (1.11.1)
multi_xml (0.5.5)
multipart-post (1.2.0)
mysql2 (0.3.16)
......@@ -450,7 +450,7 @@ GEM
quiet_assets (1.0.2)
railties (>= 3.1, < 5.0)
racc (1.4.10)
rack (1.5.3)
rack (1.5.4)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.3.0)
......@@ -470,21 +470,21 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.1.9)
actionmailer (= 4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
activemodel (= 4.1.9)
activerecord (= 4.1.9)
activesupport (= 4.1.9)
rails (4.1.11)
actionmailer (= 4.1.11)
actionpack (= 4.1.11)
actionview (= 4.1.11)
activemodel (= 4.1.11)
activerecord (= 4.1.11)
activesupport (= 4.1.11)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.9)
railties (= 4.1.11)
sprockets-rails (~> 2.0)
rails-observers (0.1.2)
activemodel (~> 4.0)
railties (4.1.9)
actionpack (= 4.1.9)
activesupport (= 4.1.9)
railties (4.1.11)
actionpack (= 4.1.11)
activesupport (= 4.1.11)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
......@@ -500,7 +500,7 @@ GEM
trollop
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.2.3)
redcarpet (3.3.1)
redis (3.1.0)
redis-actionpack (4.0.0)
actionpack (~> 4)
......@@ -634,7 +634,7 @@ GEM
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.2.4)
sprockets-rails (2.3.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
......@@ -779,7 +779,7 @@ DEPENDENCIES
html-pipeline (~> 1.11.0)
httparty
jquery-atwho-rails (~> 1.0.0)
jquery-rails (= 3.1.2)
jquery-rails (= 3.1.3)
jquery-scrollto-rails
jquery-turbolinks
jquery-ui-rails
......@@ -810,10 +810,10 @@ DEPENDENCIES
rack-cors
rack-mini-profiler
rack-oauth2 (~> 1.0.5)
rails (~> 4.1.0)
rails (= 4.1.11)
raphael-rails (~> 2.1.2)
rdoc (~> 3.6)
redcarpet (~> 3.2.3)
redcarpet (~> 3.3.0)
redis-rails
request_store
rerun (~> 0.10.0)
......
......@@ -55,7 +55,7 @@ class Dispatcher
when 'projects:merge_requests:index'
shortcut_handler = new ShortcutsNavigation()
MergeRequests.init()
when 'dashboard:show'
when 'dashboard:show', 'root:show'
new Dashboard()
new Activities()
when 'dashboard:projects:starred'
......
......@@ -8,11 +8,12 @@
class @Notes
@interval: null
constructor: (notes_url, note_ids, last_fetched_at) ->
constructor: (notes_url, note_ids, last_fetched_at, view) ->
@notes_url = notes_url
@notes_url = gon.relative_url_root + @notes_url if gon.relative_url_root?
@note_ids = note_ids
@last_fetched_at = last_fetched_at
@view = view
@noteable_url = document.URL
@initRefresh()
@setupMainTargetNoteForm()
......@@ -131,6 +132,8 @@ class @Notes
isNewNote: (note) ->
$.inArray(note.id, @note_ids) == -1
isParallelView: ->
@view == 'parallel'
###
Render note in discussion area.
......@@ -391,6 +394,7 @@ class @Notes
setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target
form.attr "rel", dataHolder.data("discussionId")
form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode")
form.find("#note_noteable_type").val dataHolder.data("noteableType")
......@@ -411,19 +415,40 @@ class @Notes
form = $(".js-new-note-form")
row = $(link).closest("tr")
nextRow = row.next()
# does it already have notes?
if nextRow.is(".notes_holder")
replyButton = nextRow.find(".js-discussion-reply-button")
if replyButton.length > 0
$.proxy(@replyToDiscussionNote, replyButton).call()
hasNotes = nextRow.is(".notes_holder")
addForm = false
targetContent = ".notes_content"
rowCssToAdd = "<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line\" colspan=\"2\"></td><td class=\"notes_content\"></td></tr>"
# In parallel view, look inside the correct left/right pane
if @isParallelView()
lineType = $(link).data("lineType")
targetContent += "." + lineType
rowCssToAdd = "<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line\"></td><td class=\"notes_content parallel old\"></td><td class=\"notes_line\"></td><td class=\"notes_content parallel new\"></td></tr>"
if hasNotes
notesContent = nextRow.find(targetContent)
if notesContent.length
replyButton = notesContent.find(".js-discussion-reply-button:visible")
if replyButton.length
e.target = replyButton[0]
$.proxy(@replyToDiscussionNote, replyButton[0], e).call()
else
# In parallel view, the form may not be present in one of the panes
noteForm = notesContent.find(".js-discussion-note-form")
if noteForm.length == 0
addForm = true
else
# add a notes row and insert the form
row.after "<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line\" colspan=\"2\"></td><td class=\"notes_content\"></td></tr>"
form.clone().appendTo row.next().find(".notes_content")
row.after rowCssToAdd
addForm = true
if addForm
newForm = form.clone()
newForm.appendTo row.next().find(targetContent)
# show the form
@setupDiscussionNoteForm $(link), row.next().find("form")
@setupDiscussionNoteForm $(link), newForm
###
Called in response to "cancel" on a diff note form.
......
class @Profile
constructor: ->
$('.edit_user .application-theme input, .edit_user .code-preview-theme input').click ->
# Submit the form
$('.edit_user').submit()
new Flash("Appearance settings saved", "notice")
# Automatically submit the Preferences form when any of its radio buttons change
$('.js-preferences-form').on 'change.preference', 'input[type=radio]', ->
$(this).parents('form').submit()
$('.update-username form').on 'ajax:before', ->
$('.loading-gif').show()
......@@ -18,7 +16,6 @@ class @Profile
$('.update-notifications').on 'ajax:complete', ->
$(this).find('.btn-save').enable()
$('.js-choose-user-avatar-button').bind "click", ->
form = $(this).closest("form")
form.find(".js-user-avatar-input").click()
......
......@@ -35,26 +35,26 @@
*/
@import "font-awesome";
/**
* UI themes:
*/
@import "themes/**/*";
/**
* Generic css (forms, nav etc):
*/
@import "generic/*";
@import "generic/**/*";
/**
* Page specific styles (issues, projects etc):
*/
@import "pages/*";
@import "pages/**/*";
/**
* Code highlight
*/
@import "highlight/*";
/**
* UI themes:
*/
@import "themes/*";
@import "highlight/**/*";
/**
* Styles for JS behaviors.
......
......@@ -98,16 +98,16 @@ header {
height: $header-height;
.title {
position: relative;
float: left;
margin: 0;
margin-left: 35px;
padding: 0 15px 0 35px;
overflow: hidden;
font-size: 18px;
line-height: $header-height;
font-weight: bold;
color: #444;
@include str-truncated(37%);
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
a {
color: #444;
......@@ -116,6 +116,10 @@ header {
}
}
}
.navbar-collapse {
float: right;
}
}
.search {
......@@ -167,10 +171,6 @@ header {
}
@media (max-width: $screen-md-max) {
header .container .title {
max-width: 43%;
}
.header-collapsed, .header-expanded {
@include collapsed-header;
}
......@@ -190,7 +190,6 @@ header {
font-size: 18px;
.title {
max-width: 70%;
}
.navbar-nav {
......
......@@ -61,8 +61,7 @@
}
.container .title {
margin-left: 15px !important;
max-width: 70% !important;
padding-left: 15px !important;
}
.issue-info, .merge-request-info {
......
......@@ -28,10 +28,6 @@
font-size: 14px;
line-height: 24px;
.str-truncated {
max-width: 76%;
}
a {
display: block;
padding: 8px 15px;
......
......@@ -17,67 +17,6 @@
}
}
/*
* Appearance settings
*
*/
.themes_opts {
label {
margin-right: 20px;
text-align: center;
.prev {
height: 80px;
width: 160px;
margin-bottom: 10px;
@include border-radius(4px);
&.classic {
background: #31363e;
}
&.default {
background: #888888;
}
&.modern {
background: #009871;
}
&.gray {
background: #373737;
}
&.violet {
background: #548;
}
&.blue {
background: #2980b9;
}
}
}
}
.code_highlight_opts {
margin-top: 10px;
label {
margin-right: 20px;
text-align: center;
.prev {
width: 160px;
margin-bottom: 10px;
img {
max-width: 100%;
@include border-radius(4px);
}
}
}
}
.oauth-buttons {
.btn-group {
margin-right: 10px;
......
.application-theme {
label {
margin-right: 20px;
text-align: center;
.preview {
@include border-radius(4px);
height: 80px;
margin-bottom: 10px;
width: 160px;
&.ui_blue {
background: $theme-blue;
}
&.ui_charcoal {
background: $theme-charcoal;
}
&.ui_graphite {
background: $theme-graphite;
}
&.ui_gray {
background: $theme-gray;
}
&.ui_green {
background: $theme-green;
}
&.ui_violet {
background: $theme-violet;
}
}
}
}
.syntax-theme {
label {
margin-right: 20px;
text-align: center;
.preview {
margin-bottom: 10px;
width: 160px;
img {
@include border-radius(4px);
max-width: 100%;
}
}
}
}
/**
* Styles the GitLab application with a specific color theme
*
* $color-light -
* $color -
* $color-darker -
* $color-dark -
*/
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
header {
&.navbar-gitlab {
......@@ -77,3 +85,36 @@
}
}
}
$theme-blue: #2980B9;
$theme-charcoal: #474D57;
$theme-graphite: #888888;
$theme-gray: #373737;
$theme-green: #019875;
$theme-violet: #554488;
body {
&.ui_blue {
@include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099);
}
&.ui_charcoal {
@include gitlab-theme(#979DA7, $theme-charcoal, #373D47, #24272D);
}
&.ui_graphite {
@include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666);
}
&.ui_gray {
@include gitlab-theme(#979797, $theme-gray, #272727, #222222);
}
&.ui_green {
@include gitlab-theme(#AADDCC, $theme-green, #018865, #017855);
}
&.ui_violet {
@include gitlab-theme(#9988CC, $theme-violet, #443366, #332255);
}
}
/**
* This file represent some UI that can be changed
* during web app restyle or theme select.
*
*/
.ui_basic {
@include gitlab-theme(#CCCCCC, #888888, #777777, #666666);
}
/**
* Blue GitLab UI theme
*/
.ui_blue {
@include gitlab-theme(#BECDE9, #2980b9, #1970a9, #096099);
}
/**
* Violet GitLab UI theme
*/
.ui_color {
@include gitlab-theme(#98C, #548, #436, #325);
}
/**
* Gray GitLab UI theme
*/
.ui_gray {
@include gitlab-theme(#979797, #373737, #272727, #222222);
}
/**
* Classic GitLab UI theme
*/
.ui_mars {
@include gitlab-theme(#979DA7, #474D57, #373D47, #24272D);
}
/**
* Modern GitLab UI theme
*/
.ui_modern {
@include gitlab-theme(#ADC, #019875, #018865, #017855);
}
......@@ -41,6 +41,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:help_text,
:after_sign_out_path,
:max_attachment_size,
:session_expire_delay,
:default_project_visibility,
:default_snippet_visibility,
:restricted_signup_domains_raw,
......
class Profiles::PreferencesController < Profiles::ApplicationController
before_action :user
def show
end
def update
begin
if @user.update_attributes(preferences_params)
flash[:notice] = 'Preferences saved.'
else
flash[:alert] = 'Failed to save preferences.'
end
rescue ArgumentError => e
# Raised when `dashboard` is given an invalid value.
flash[:alert] = "Failed to save preferences (#{e.message})."
end
respond_to do |format|
format.html { redirect_to profile_preferences_path }
format.js
end
end
private
def user
@user = current_user
end
def preferences_params
params.require(:user).permit(
:color_scheme_id,
:dashboard,
:theme_id
)
end
end
......@@ -8,9 +8,6 @@ class ProfilesController < Profiles::ApplicationController
def show
end
def design
end
def applications
@applications = current_user.oauth_applications
@authorized_tokens = current_user.oauth_authorized_tokens
......@@ -29,7 +26,6 @@ class ProfilesController < Profiles::ApplicationController
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
......@@ -65,10 +61,21 @@ class ProfilesController < Profiles::ApplicationController
def user_params
params.require(:user).permit(
:email, :password, :password_confirmation, :bio, :name,
:username, :skype, :linkedin, :twitter, :website_url,
:color_scheme_id, :theme_id, :avatar, :hide_no_ssh_key,
:hide_no_password, :location, :public_email
:avatar,
:bio,
:email,
:hide_no_password,
:hide_no_ssh_key,
:linkedin,
:location,
:name,
:password,
:password_confirmation,
:public_email,
:skype,
:twitter,
:username,
:website_url
)
end
end
......@@ -77,11 +77,24 @@ class Projects::NotesController < Projects::ApplicationController
end
def note_to_discussion_html(note)
if params[:view] == 'parallel'
template = "projects/notes/_diff_notes_with_reply_parallel"
locals =
if params[:line_type] == 'old'
{ notes_left: [note], notes_right: [] }
else
{ notes_left: [], notes_right: [note] }
end
else
template = "projects/notes/_diff_notes_with_reply"
locals = { notes: [note] }
end
render_to_string(
"projects/notes/_diff_notes_with_reply",
template,
layout: false,
formats: [:html],
locals: { notes: [note] }
locals: locals
)
end
......
# RootController
#
# This controller exists solely to handle requests to `root_url`. When a user is
# logged in and has customized their `dashboard` setting, they will be
# redirected to their preferred location.
#
# For users who haven't customized the setting, we simply delegate to
# `DashboardController#show`, which is the default.
class RootController < DashboardController
before_action :redirect_to_custom_dashboard, only: [:show]
def show
super
end
private
def redirect_to_custom_dashboard
return unless current_user
case current_user.dashboard
when 'stars'
redirect_to starred_dashboard_projects_path
else
return
end
end
end
......@@ -2,26 +2,6 @@ require 'digest/md5'
require 'uri'
module ApplicationHelper
COLOR_SCHEMES = {
1 => 'white',
2 => 'dark',
3 => 'solarized-light',
4 => 'solarized-dark',
5 => 'monokai',
}
COLOR_SCHEMES.default = 'white'
# Helper method to access the COLOR_SCHEMES
#
# The keys are the `color_scheme_ids`
# The values are the `name` of the scheme.
#
# The preview images are `name-scheme-preview.png`
# The stylesheets should use the css class `.name`
def color_schemes
COLOR_SCHEMES.freeze
end
# Check if a particular controller is the current one
#
# args - One or more controller names to check
......@@ -138,18 +118,6 @@ module ApplicationHelper
Emoji.names.to_s
end
def app_theme
Gitlab::Theme.css_class_by_id(current_user.try(:theme_id))
end
def theme_type
Gitlab::Theme.type_css_class_by_id(current_user.try(:theme_id))
end
def user_color_scheme_class
COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
end
# Define whenever show last push event
# with suggestion to create MR
def show_last_push_widget?(event)
......
......@@ -2,6 +2,7 @@ require 'nokogiri'
module GitlabMarkdownHelper
include Gitlab::Markdown
include PreferencesHelper
# Use this in places where you would normally use link_to(gfm(...), ...).
#
......
......@@ -47,7 +47,7 @@ module NotesHelper
}.to_json
end
def link_to_new_diff_note(line_code)
def link_to_new_diff_note(line_code, line_type = nil)
discussion_id = Note.build_discussion_id(
@comments_target[:noteable_type],
@comments_target[:noteable_id] || @comments_target[:commit_id],
......@@ -59,7 +59,8 @@ module NotesHelper
noteable_id: @comments_target[:noteable_id],
commit_id: @comments_target[:commit_id],
line_code: line_code,
discussion_id: discussion_id
discussion_id: discussion_id,
line_type: line_type
}
button_tag(class: 'btn add-diff-note js-add-diff-note-button',
......@@ -69,7 +70,7 @@ module NotesHelper
end
end
def link_to_reply_diff(note)
def link_to_reply_diff(note, line_type = nil)
return unless current_user
data = {
......@@ -77,7 +78,8 @@ module NotesHelper
noteable_id: note.noteable_id,
commit_id: note.commit_id,
line_code: note.line_code,
discussion_id: note.discussion_id
discussion_id: note.discussion_id,
line_type: line_type
}
button_tag class: 'btn reply-btn js-discussion-reply-button',
......
# Helper methods for per-User preferences
module PreferencesHelper
COLOR_SCHEMES = {
1 => 'white',
2 => 'dark',
3 => 'solarized-light',
4 => 'solarized-dark',
5 => 'monokai',
}
COLOR_SCHEMES.default = 'white'
# Helper method to access the COLOR_SCHEMES
#
# The keys are the `color_scheme_ids`
# The values are the `name` of the scheme.
#
# The preview images are `name-scheme-preview.png`
# The stylesheets should use the css class `.name`
def color_schemes
COLOR_SCHEMES.freeze
end
# Maps `dashboard` values to more user-friendly option text
DASHBOARD_CHOICES = {
projects: 'Your Projects (default)',
stars: 'Starred Projects'
}.with_indifferent_access.freeze
# Returns an Array usable by a select field for more user-friendly option text
def dashboard_choices
defined = User.dashboards
if defined.size != DASHBOARD_CHOICES.size
# Ensure that anyone adding new options updates this method too
raise RuntimeError, "`User` defines #{defined.size} dashboard choices," +
" but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}."
else
defined.map do |key, _|
# Use `fetch` so `KeyError` gets raised when a key is missing
[DASHBOARD_CHOICES.fetch(key), key]
end
end
end
def user_application_theme
theme = Gitlab::Themes.by_id(current_user.try(:theme_id))
theme.css_class
end
def user_color_scheme_class
COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
end
end
......@@ -16,6 +16,7 @@
# help_text :text
# restricted_visibility_levels :text
# max_attachment_size :integer default(10), not null
# session_expire_delay :integer default(10080), not null
# default_project_visibility :integer
# default_snippet_visibility :integer
# restricted_signup_domains :text
......@@ -28,6 +29,10 @@ class ApplicationSetting < ActiveRecord::Base
serialize :restricted_signup_domains, Array
attr_accessor :restricted_signup_domains_raw
validates :session_expire_delay,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :home_page_url,
allow_blank: true,
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" },
......@@ -62,6 +67,7 @@ class ApplicationSetting < ActiveRecord::Base
sign_in_text: Settings.extra['sign_in_text'],
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
session_expire_delay: Settings.gitlab['session_expire_delay'],
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
restricted_signup_domains: Settings.gitlab['restricted_signup_domains']
......
......@@ -31,7 +31,7 @@ class Note < ActiveRecord::Base
participant :author, :mentioned_users
belongs_to :project
belongs_to :noteable, polymorphic: true
belongs_to :noteable, polymorphic: true, touch: true
belongs_to :author, class_name: "User"
delegate :name, to: :project, prefix: true
......
......@@ -752,4 +752,12 @@ class Project < ActiveRecord::Base
errors.add(:base, 'Failed create wiki')
false
end
def reference_issue_tracker?
default_issues_tracker? || jira_tracker_active?
end
def jira_tracker_active?
jira_tracker? && jira_service.active
end
end
......@@ -40,10 +40,14 @@ class GitlabCiService < CiService
def execute(data)
return unless supported_events.include?(data[:object_kind])
ci_yaml_file = ci_yaml_file(data)
sha = data[:checkout_sha]
if ci_yaml_file
data.merge!(ci_yaml_file: ci_yaml_file)
if sha.present?
file = ci_yaml_file(sha)
if file && file.data
data.merge!(ci_yaml_file: file.data)
end
end
service_hook.execute(data)
......@@ -129,15 +133,15 @@ class GitlabCiService < CiService
private
def ci_yaml_file(data)
ref = data[:checkout_sha]
repo = project.repository
commit = repo.commit(ref)
blob = Gitlab::Git::Blob.find(repo, commit.id, ".gitlab-ci.yml")
blob && blob.data
def ci_yaml_file(sha)
repository.blob_at(sha, '.gitlab-ci.yml')
end
def fork_registration_path
project_url.sub(/projects\/\d*/, "#{API_PREFIX}/forks")
end
def repository
project.repository
end
end
......@@ -85,18 +85,13 @@ class IssueTrackerService < Service
result = false
begin
url = URI.parse(self.project_url)
response = HTTParty.head(self.project_url, verify: true)
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
if response
message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
result = true
end
rescue Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => error
rescue HTTParty::Error, 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)
......
......@@ -50,12 +50,13 @@
# bitbucket_access_token :string(255)
# bitbucket_access_token_secret :string(255)
# location :string(255)
# public_email :string(255) default(""), not null
# encrypted_otp_secret :string(255)
# encrypted_otp_secret_iv :string(255)
# encrypted_otp_secret_salt :string(255)
# otp_required_for_login :boolean
# otp_backup_codes :text
# public_email :string(255) default(""), not null
# dashboard :integer default(0)
#
require 'carrierwave/orm/activerecord'
......@@ -734,4 +735,8 @@ class User < ActiveRecord::Base
def can_be_removed?
!solo_owned_groups.present?
end
# User's Dashboard preference
# Note: When adding an option, it MUST go on the end of the array.
enum dashboard: [:projects, :stars]
end
......@@ -92,18 +92,24 @@ class GitPushService
end
end
# Create cross-reference notes for any other references. Omit any issues that were referenced in an
# issue-closing phrase, or have already been mentioned from this commit (probably from this commit
# being pushed to a different branch).
refs = commit.references(project, user) - issues_to_close
refs.reject! { |r| commit.has_mentioned?(r) }
if project.reference_issue_tracker?
create_cross_reference_notes(commit, issues_to_close)
end
end
end
if refs.present?
author ||= commit_user(commit)
def create_cross_reference_notes(commit, issues_to_close)
# Create cross-reference notes for any other references. Omit any issues that were referenced in an
# issue-closing phrase, or have already been mentioned from this commit (probably from this commit
# being pushed to a different branch).
refs = commit.references(project, user) - issues_to_close
refs.reject! { |r| commit.has_mentioned?(r) }
refs.each do |r|
Note.create_cross_reference_note(r, commit, author)
end
if refs.present?
author ||= commit_user(commit)
refs.each do |r|
Note.create_cross_reference_note(r, commit, author)
end
end
end
......
module Issues
class CloseService < Issues::BaseService
def execute(issue, commit = nil)
if issue.close
if project.default_issues_tracker? && issue.close
event_service.close_issue(issue, current_user)
create_note(issue, commit)
notification_service.close_issue(issue, current_user)
......
......@@ -216,13 +216,15 @@ class SystemNoteService
# Check if a cross-reference is disallowed
#
# This method prevents adding a "mentioned in !1" note on every single commit
# in a merge request.
# in a merge request. Additionally, it prevents the creation of references to
# external issues (which would fail).
#
# noteable - Noteable object being referenced
# mentioner - Mentionable object
#
# Returns Boolean
def self.cross_reference_disallowed?(noteable, mentioner)
return true if noteable.is_a?(ExternalIssue) && !noteable.project.jira_tracker_active?
return false unless mentioner.is_a?(MergeRequest)
return false unless noteable.is_a?(Commit)
......
......@@ -88,6 +88,11 @@
= f.label :max_attachment_size, 'Maximum attachment size (MB)', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :max_attachment_size, class: 'form-control', min: 0
.form-group
= f.label :session_expire_delay, 'Session duration (minutes)', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :session_expire_delay, class: 'form-control'
%span.help-block#session_expire_delay_help_block GitLab restart is required to apply changes
.form-group
= f.label :restricted_signup_domains, 'Restricted domains for sign-ups', class: 'control-label col-sm-2'
.col-sm-10
......
......@@ -12,8 +12,7 @@
- if @group.new_record?
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
.alert.alert-info
= render 'shared/group_tips'
.form-actions
......
......@@ -92,8 +92,7 @@
= namespace_select_tag :new_namespace_id, selected: params[:namespace_id], class: 'input-large'
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
= f.submit 'Transfer', class: 'btn btn-primary'
.col-md-6
......
= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f|
- if application.errors.any?
.alert.alert-danger{"data-alert" => ""}
%p Whoops! Check your form for possible errors
= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do
= f.label :name, class: 'col-sm-2 control-label'
.alert.alert-danger
%ul
- application.errors.full_messages.each do |msg|
%li= msg
.form-group
= f.label :name, class: 'control-label'
.col-sm-10
= f.text_field :name, class: 'form-control'
= doorkeeper_errors_for application, :name
= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do
= f.label :redirect_uri, class: 'col-sm-2 control-label'
= f.text_field :name, class: 'form-control', required: true
.form-group
= f.label :redirect_uri, class: 'control-label'
.col-sm-10
= f.text_area :redirect_uri, class: 'form-control'
= doorkeeper_errors_for application, :redirect_uri
= f.text_area :redirect_uri, class: 'form-control', required: true
%span.help-block
Use one line per URI
- if Doorkeeper.configuration.native_redirect_uri
......@@ -19,6 +24,7 @@
Use
%code= Doorkeeper.configuration.native_redirect_uri
for local tests
.form-actions
= f.submit 'Submit', class: "btn btn-primary wide"
= link_to "Cancel", applications_profile_path, class: "btn btn-default"
= f.submit 'Submit', class: "btn btn-create"
= link_to "Cancel", applications_profile_path, class: "btn btn-cancel"
%h3.page-title New application
- page_title "New Application"
%h3.page-title New Application
%hr
= render 'form', application: @application
\ No newline at end of file
......@@ -4,7 +4,7 @@
%span You pushed to
= link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
%strong= event.ref_name
at
%span at
%strong= link_to_project event.project
#{time_ago_with_tooltip(event.created_at)}
......
......@@ -13,6 +13,3 @@
.public-projects
%ul.bordered-list
= render @trending_projects
.center.append-bottom-20
= link_to 'Show all projects', explore_projects_path, class: 'btn btn-primary'
......@@ -11,8 +11,7 @@
= render 'shared/group_form', f: f
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
= image_tag group_icon(@group), alt: '', class: 'avatar group-avatar s160'
%p.light
- if @group.avatar?
......
......@@ -13,8 +13,7 @@
= render 'shared/choose_group_avatar_button', f: f
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
= render 'shared/group_tips'
.form-actions
......
#modal-shortcuts.modal.hide{tabindex: -1}
#modal-shortcuts.modal{tabindex: -1}
.modal-dialog
.modal-content
.modal-header
......
!!! 5
%html{ lang: "en"}
= render "layouts/head"
%body{class: "#{app_theme}", :'data-page' => body_data_page}
/ Ideally this would be inside the head, but turbolinks only evaluates page-specific JS in the body.
%body{class: "#{user_application_theme}", 'data-page' => body_data_page}
-# Ideally this would be inside the head, but turbolinks only evaluates page-specific JS in the body.
= yield :scripts_body_top
- if current_user
= render "layouts/header/default", title: header_title
- else
......
!!! 5
%html{ lang: "en"}
= render "layouts/head"
%body.ui_mars.login-page.application
%body.ui_charcoal.login-page.application
= render "layouts/header/empty"
= render "layouts/broadcast"
.container.navless-container
......
!!! 5
%html{ lang: "en"}
= render "layouts/head"
%body{class: "#{app_theme} application"}
%body{class: "#{user_application_theme} application"}
= render "layouts/header/empty"
.container.navless-container
= render "layouts/flash"
......
......@@ -5,10 +5,7 @@
= brand_header_logo
%h3 GitLab
.header-content
%h1.title
= title
%button.navbar-toggle
%button.navbar-toggle{type: 'button'}
%span.sr-only Toggle navigation
= icon('bars')
......@@ -43,4 +40,6 @@
= link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do
= icon('sign-out')
%h1.title= title
= render 'shared/outdated_browser'
......@@ -5,10 +5,10 @@
= brand_header_logo
%h3 GitLab
.header-content
%h1.title= title
- unless current_controller?('sessions')
.pull-right
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success btn-sm'
%h1.title= title
= render 'shared/outdated_browser'
%ul.nav.nav-sidebar
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
= link_to root_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
= nav_link(path: ['dashboard#show', 'root#show'], html_options: {class: 'home'}) do
= link_to dashboard_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
= icon('dashboard fw')
%span
Your Projects
......
......@@ -9,7 +9,7 @@
= icon('gear fw')
%span
Account
= nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do
= nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new', 'applications#create']) do
= link_to applications_profile_path, title: 'Applications', data: {placement: 'right'} do
= icon('cloud fw')
%span
......@@ -38,11 +38,12 @@
%span
SSH Keys
%span.count= current_user.keys.count
= nav_link(path: 'profiles#design') do
= link_to design_profile_path, title: 'Design', data: {placement: 'right'} do
= nav_link(controller: :preferences) do
= link_to profile_preferences_path, title: 'Preferences', data: {placement: 'right'} do
-# TODO (rspeicher): Better icon?
= icon('image fw')
%span
Design
Preferences
= nav_link(path: 'profiles#history') do
= link_to history_profile_path, title: 'History', data: {placement: 'right'} do
= icon('history fw')
......
- page_title "Account"
%h3.page-title
= page_title
%p.light
Change your username and basic account settings.
%hr
- if current_user.ldap_user?
.alert.alert-info
Some options are unavailable for LDAP accounts
.account-page
.panel.panel-default.update-token
.panel-heading
Reset Private token
.panel-body
= form_for @user, url: reset_private_token_profile_path, method: :put do |f|
.data
%p
Your private token is used to access application resources without authentication.
%br
It can be used for atom feeds or the API.
%span.cred
Keep it secret!
%p.cgray
- if current_user.private_token
= text_field_tag "token", current_user.private_token, class: "form-control"
%div
= f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default btn-build-token"
- else
%span You don`t have one yet. Click generate to fix it.
= f.submit 'Generate', class: "btn btn-default btn-build-token"
.panel.panel-default
.panel-heading
Two-factor Authentication
.panel-body
- if current_user.otp_required_for_login
.pull-right
= link_to 'Disable Two-factor Authentication', profile_two_factor_auth_path, method: :delete, class: 'btn btn-close btn-sm',
data: { confirm: 'Are you sure?' }
%p.text-success
%strong
Two-factor Authentication is enabled
%p
If you lose your recovery codes you can
%strong
= succeed ',' do
= link_to 'generate new ones', codes_profile_two_factor_auth_path, method: :post, data: { confirm: 'Are you sure?' }
invalidating all previous codes.
- else
%p
Increase your account's security by enabling two-factor authentication (2FA).
%p
Each time you log in you’ll be required to provide your username and
password as usual, plus a randomly-generated code from your phone.
%div
= link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success'
- if show_profile_social_tab?
.panel.panel-default
.panel-heading
Connected Accounts
.panel-body
.oauth-buttons.append-bottom-10
%p Click on icon to activate signin with one of the following services
- enabled_social_providers.each do |provider|
.btn-group
= link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider),
method: :post, class: "btn btn-lg #{'active' if oauth_active?(provider)}"
- if oauth_active?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
= icon('close')
- if show_profile_username_tab?
.panel.panel-warning.update-username
.panel-heading
Change Username
.panel-body
= form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
%p
Changing your username will change path to all personal projects!
%div
= f.text_field :username, required: true, class: 'form-control'
&nbsp;
.loading-gif.hide
%p
= icon('spinner spin')
Saving new username
%p.light
= user_url(@user)
%div
= f.submit 'Save username', class: "btn btn-warning"
- if show_profile_remove_tab?
.panel.panel-danger.remove-account
.panel-heading
Remove account
.panel-body
- if @user.can_be_removed?
%p Deleting an account has the following effects:
%ul
%li All user content like authored issues, snippets, comments will be removed
- rp = current_user.personal_projects.count
- unless rp.zero?
%li #{pluralize rp, 'personal project'} will be removed and cannot be restored
= link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
- else
- if @user.solo_owned_groups.present?
%p
Your account is currently an owner in these groups:
%strong #{@user.solo_owned_groups.map(&:name).join(', ')}
%p
You must transfer ownership or delete these groups before you can delete your account.
\ No newline at end of file
- page_title "Account"
%h3.page-title
= page_title
%p.light
Change your username and basic account settings.
%hr
- if current_user.ldap_user?
.alert.alert-info
Some options are unavailable for LDAP accounts
.account-page
.panel.panel-default.update-token
.panel-heading
Reset Private token
.panel-body
= form_for @user, url: reset_private_token_profile_path, method: :put do |f|
.data
%p
Your private token is used to access application resources without authentication.
%br
It can be used for atom feeds or the API.
%span.cred
Keep it secret!
%p.cgray
- if current_user.private_token
= text_field_tag "token", current_user.private_token, class: "form-control"
%div
= f.submit 'Reset private token', data: { confirm: "Are you sure?" }, class: "btn btn-default btn-build-token"
- else
%span You don`t have one yet. Click generate to fix it.
= f.submit 'Generate', class: "btn btn-default btn-build-token"
.panel.panel-default
.panel-heading
Two-factor Authentication
.panel-body
- if current_user.otp_required_for_login
.pull-right
= link_to 'Disable Two-factor Authentication', profile_two_factor_auth_path, method: :delete, class: 'btn btn-close btn-sm',
data: { confirm: 'Are you sure?' }
%p.text-success
%strong
Two-factor Authentication is enabled
%p
If you lose your recovery codes you can
%strong
= succeed ',' do
= link_to 'generate new ones', codes_profile_two_factor_auth_path, method: :post, data: { confirm: 'Are you sure?' }
invalidating all previous codes.
- else
%p
Increase your account's security by enabling two-factor authentication (2FA).
%p
Each time you log in you’ll be required to provide your username and
password as usual, plus a randomly-generated code from your phone.
%div
= link_to 'Enable Two-factor Authentication', new_profile_two_factor_auth_path, class: 'btn btn-success'
- if show_profile_social_tab?
.panel.panel-default
.panel-heading
Connected Accounts
.panel-body
.oauth-buttons.append-bottom-10
%p Click on icon to activate signin with one of the following services
- enabled_social_providers.each do |provider|
.btn-group
= link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider),
method: :post, class: "btn btn-lg #{'active' if oauth_active?(provider)}"
- if oauth_active?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
= icon('close')
- if show_profile_username_tab?
.panel.panel-warning.update-username
.panel-heading
Change Username
.panel-body
= form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
%p
Changing your username will change path to all personal projects!
%div
= f.text_field :username, required: true, class: 'form-control'
&nbsp;
.loading-gif.hide
%p
= icon('spinner spin')
Saving new username
%p.light
= user_url(@user)
%div
= f.submit 'Save username', class: "btn btn-warning"
- if show_profile_remove_tab?
.panel.panel-danger.remove-account
.panel-heading
Remove account
.panel-body
- if @user.can_be_removed?
%p Deleting an account has the following effects:
%ul
%li All user content like authored issues, snippets, comments will be removed
- rp = current_user.personal_projects.count
- unless rp.zero?
%li #{pluralize rp, 'personal project'} will be removed and cannot be restored
= link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
- else
- if @user.solo_owned_groups.present?
%p
Your account is currently an owner in these groups:
%strong #{@user.solo_owned_groups.map(&:name).join(', ')}
%p
You must transfer ownership or delete these groups before you can delete your account.
- page_title "Design"
%h3.page-title
= page_title
%p.light
Appearance settings will be saved to your profile and made available across all devices.
%hr
= form_for @user, url: profile_path, remote: true, method: :put do |f|
.panel.panel-default.application-theme
.panel-heading
Application theme
.panel-body
.themes_opts
= label_tag do
.prev.default
= f.radio_button :theme_id, 1
Graphite
= label_tag do
.prev.classic
= f.radio_button :theme_id, 2
Charcoal
= label_tag do
.prev.modern
= f.radio_button :theme_id, 3
Green
= label_tag do
.prev.gray
= f.radio_button :theme_id, 4
Gray
= label_tag do
.prev.violet
= f.radio_button :theme_id, 5
Violet
= label_tag do
.prev.blue
= f.radio_button :theme_id, 6
Blue
%br
.clearfix
.panel.panel-default.code-preview-theme
.panel-heading
Code preview theme
.panel-body
.code_highlight_opts
- color_schemes.each do |color_scheme_id, color_scheme|
= label_tag do
.prev
= image_tag "#{color_scheme}-scheme-preview.png"
= f.radio_button :color_scheme_id, color_scheme_id
= color_scheme.gsub(/[-_]+/, ' ').humanize
- page_title 'Preferences'
%h3.page-title
= page_title
%p.light
These settings allow you to customize the appearance and behavior of the site.
They are saved with your account and will persist to any device you use to
access the site.
%hr
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'js-preferences-form form-horizontal'} do |f|
.panel.panel-default.application-theme
.panel-heading
Application theme
.panel-body
- Gitlab::Themes.each do |theme|
= label_tag do
.preview{class: theme.css_class}
= f.radio_button :theme_id, theme.id
= theme.name
.panel.panel-default.syntax-theme
.panel-heading
Syntax highlighting theme
.panel-body
- color_schemes.each do |color_scheme_id, color_scheme|
= label_tag do
.preview= image_tag "#{color_scheme}-scheme-preview.png"
= f.radio_button :color_scheme_id, color_scheme_id
= color_scheme.tr('-_', ' ').titleize
.panel.panel-default
.panel-heading
Behavior
.panel-body
.form-group
= f.label :dashboard, class: 'control-label' do
Default Dashboard
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank')
.col-sm-10
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
.panel-footer
= f.submit 'Save', class: 'btn btn-save'
// Remove body class for any previous theme, re-add current one
$('body').removeClass('<%= Gitlab::Themes.body_classes %>')
$('body').addClass('<%= user_application_theme %>')
// Re-enable the "Save" button
$('input[type=submit]').enable()
// Show the notice flash message
new Flash('<%= flash.discard(:notice) %>', 'notice')
......@@ -109,6 +109,5 @@
.row
.col-md-7
.form-group
.col-sm-2 &nbsp;
.col-sm-10
.col-sm-offset-2.col-sm-10
= f.submit 'Save changes', class: "btn btn-success"
// Remove body class for any previous theme, re-add current one
$('body').removeClass('<%= Gitlab::Theme.body_classes %>')
$('body').addClass('<%= app_theme %> <%= theme_type %>')
%div#bitbucket_import_modal.modal.hide
%div#bitbucket_import_modal.modal
.modal-dialog
.modal-content
.modal-header
......
%div#github_import_modal.modal.hide
%div#github_import_modal.modal
.modal-dialog
.modal-content
.modal-header
......
%div#gitlab_import_modal.modal.hide
%div#gitlab_import_modal.modal
.modal-dialog
.modal-content
.modal-header
......
- if issuable.errors.any?
.row
.col-sm-10.col-sm-offset-2
.col-sm-offset-2.col-sm-10
.alert.alert-danger
- issuable.errors.full_messages.each do |msg|
%span= msg
......
#modal-remove-blob.modal.hide
#modal-remove-blob.modal
.modal-dialog
.modal-content
.modal-header
......@@ -13,8 +13,7 @@
= render 'shared/commit_message_container', params: params,
placeholder: 'Removed this file because...'
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
= button_tag 'Remove file', class: 'btn btn-remove btn-remove-file'
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
......
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
= render "commit_box"
= render "projects/diffs/diffs", diffs: @diffs, project: @project
= render "projects/notes/notes_with_form"
= render "projects/notes/notes_with_form", view: params[:view]
......@@ -18,6 +18,8 @@
- elsif type_left == 'old' || type_left.nil?
%td.old_line{id: line_code_left, class: "#{type_left}"}
= link_to raw(line_number_left), "##{line_code_left}", id: line_code_left
- if @comments_allowed && can?(current_user, :write_note, @project)
= link_to_new_diff_note(line_code_left, 'old')
%td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw line_content_left
- if type_right == 'new'
......@@ -29,12 +31,14 @@
%td.new_line{id: new_line_code, class: "#{new_line_class}", data: { linenumber: line_number_right }}
= link_to raw(line_number_right), "##{new_line_code}", id: new_line_code
- if @comments_allowed && can?(current_user, :write_note, @project)
= link_to_new_diff_note(line_code_right, 'new')
%td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw line_content_right
- if @reply_allowed
- comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right)
- if comments_left.present? || comments_right.present?
= render "projects/notes/diff_notes_with_reply_parallel", notes1: comments_left, notes2: comments_right
= render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right
- if diff_file.diff.diff.blank? && diff_file.mode_changed?
.file-mode-changed
......
......@@ -82,8 +82,7 @@
%legend
Project avatar:
.form-group
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
- if @project.avatar?
= project_icon("#{@project.namespace.to_param}/#{@project.to_param}", alt: '', class: 'avatar project-avatar s160')
%p.light
......
= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form' } do |f|
-if @label.errors.any?
.row
.col-sm-10.col-sm-offset-2
.col-sm-offset-2.col-sm-10
.alert.alert-danger
- @label.errors.full_messages.each do |msg|
%span= msg
......
%div#modal_merge_info.modal.hide
%div#modal_merge_info.modal
.modal-dialog
.modal-content
.modal-header
......
- note1 = notes1.present? ? notes1.first : nil
- note2 = notes2.present? ? notes2.first : nil
- note1 = notes_left.present? ? notes_left.first : nil
- note2 = notes_right.present? ? notes_right.first : nil
%tr.notes_holder
- if note1
%td.notes_line
%td.notes_line.old
%span.btn.disabled
%i.fa.fa-comment
= notes1.count
%td.notes_content.parallel
= notes_left.count
%td.notes_content.parallel.old
%ul.notes{ rel: note1.discussion_id }
= render notes1
= render notes_left
.discussion-reply-holder
= link_to_reply_diff(note1)
= link_to_reply_diff(note1, 'old')
- else
%td= ""
%td= ""
%td.notes_line.old= ""
%td.notes_content.parallel.old= ""
- if note2
%td.notes_line
%td.notes_line.new
%span.btn.disabled
%i.fa.fa-comment
= notes2.count
%td.notes_content.parallel
= notes_right.count
%td.notes_content.parallel.new
%ul.notes{ rel: note2.discussion_id }
= render notes2
= render notes_right
.discussion-reply-holder
= link_to_reply_diff(note2)
= link_to_reply_diff(note2, 'new')
- else
%td= ""
%td= ""
%td.notes_line.new= ""
%td.notes_content.parallel.new= ""
= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f|
= hidden_field_tag :view, params[:view]
= hidden_field_tag :line_type
= note_target_fields(@note)
= f.hidden_field :commit_id
= f.hidden_field :line_code
......
......@@ -4,7 +4,7 @@
.js-main-target-form
- if can? current_user, :write_note, @project
= render "projects/notes/form"
= render "projects/notes/form", view: params[:view]
:javascript
new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i})
new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{params[:view]}")
......@@ -12,8 +12,7 @@
= f.select :format, options_for_select(ProjectWiki::MARKUPS, {selected: @page.format}), {}, class: "form-control"
.row
.col-sm-2
.col-sm-10
.col-sm-offset-2.col-sm-10
%p.cgray
To link to a (new) page you can just type
%code [Link Title](page-slug)
......
%div#modal-new-wiki.modal.hide
%div#modal-new-wiki.modal
.modal-dialog
.modal-content
.modal-header
......
......@@ -3,6 +3,7 @@
.input-group-addon.git-protocols
.input-group-btn
%button{ |
type: 'button', |
class: "btn btn-sm #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", |
:"data-clone" => project.ssh_url_to_repo, |
:"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH",
......@@ -11,6 +12,7 @@
SSH
.input-group-btn
%button{ |
type: 'button', |
class: "btn btn-sm #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", |
:"data-clone" => project.http_url_to_repo, |
:"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}",
......
#modal-confirm-danger.modal.hide{tabindex: -1}
#modal-confirm-danger.modal{tabindex: -1}
.modal-dialog
.modal-content
.modal-header
......
......@@ -3,8 +3,6 @@
- if avatar
.dash-project-avatar
= project_icon(project, alt: '', class: 'avatar project-avatar s40')
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
%span.str-truncated
%span.namespace-name
- if project.namespace
......
......@@ -12,8 +12,8 @@
= render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: true, form_model: @snippet
.form-group
.file-editor
.file-editor
.form-group
= f.label :file_name, "File", class: 'control-label'
.col-sm-10
.file-holder.snippet
......
......@@ -62,12 +62,13 @@ production: &base
# default_can_create_group: false # default: true
# username_changing_enabled: false # default: true - User can change her username/namespace
## Default theme
## BASIC = 1
## MARS = 2
## MODERN = 3
## GRAY = 4
## COLOR = 5
## Default theme ID
## 1 - Graphite
## 2 - Charcoal
## 3 - Green
## 4 - Gray
## 5 - Violet
## 6 - Blue
# default_theme: 2 # default: 2
## Automatic issue closing
......
......@@ -136,7 +136,7 @@ Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_projects_limit'] ||= 10
Settings.gitlab['default_branch_protection'] ||= 2
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil?
Settings.gitlab['default_theme'] = Gitlab::Themes::APPLICATION_DEFAULT if Settings.gitlab['default_theme'].nil?
Settings.gitlab['host'] ||= 'localhost'
Settings.gitlab['ssh_host'] ||= Settings.gitlab.host
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
......@@ -164,6 +164,7 @@ Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e
Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab['max_attachment_size'] ||= 10
Settings.gitlab['session_expire_delay'] ||= 10080
Settings.gitlab.default_projects_features['issues'] = true if Settings.gitlab.default_projects_features['issues'].nil?
Settings.gitlab.default_projects_features['merge_requests'] = true if Settings.gitlab.default_projects_features['merge_requests'].nil?
Settings.gitlab.default_projects_features['wiki'] = true if Settings.gitlab.default_projects_features['wiki'].nil?
......
......@@ -20,3 +20,11 @@ OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_s
OmniAuth.config.before_request_phase do |env|
OmniAuth::RequestForgeryProtection.new(env).call
end
if Gitlab.config.omniauth.enabled
Gitlab.config.omniauth.providers.each do |provider|
if provider['name'] == 'kerberos'
require 'omniauth-kerberos'
end
end
end
# Be sure to restart your server when you modify this file.
require 'gitlab/current_settings'
include Gitlab::CurrentSettings
Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay
Gitlab::Application.config.session_store(
:redis_store, # Using the cookie_store would enable session replay attacks.
servers: Gitlab::Application.config.cache_store[1].merge(namespace: 'session:gitlab'), # re-use the Redis config from the Rails cache store
key: '_gitlab_session',
secure: Gitlab.config.gitlab.https,
httponly: true,
expire_after: 1.week,
expire_after: Settings.gitlab['session_expire_delay'] * 60,
path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
)
......@@ -223,7 +223,6 @@ Gitlab::Application.routes.draw do
resource :profile, only: [:show, :update] do
member do
get :history
get :design
get :applications
put :reset_private_token
......@@ -242,6 +241,7 @@ Gitlab::Application.routes.draw do
put :reset
end
end
resource :preferences, only: [:show, :update]
resources :keys
resources :emails, only: [:index, :create, :destroy]
resource :avatar, only: [:destroy]
......@@ -330,7 +330,7 @@ Gitlab::Application.routes.draw do
get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
end
root to: "dashboard#show"
root to: "root#show"
#
# Project Area
......
......@@ -12,7 +12,7 @@ admin = User.create(
username: 'root',
password: password,
password_expires_at: expire_time,
theme_id: Gitlab::Theme::MARS
theme_id: Gitlab::Themes::APPLICATION_DEFAULT
)
......
class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration
def change
add_column :application_settings, :session_expire_delay, :integer, default: 10080, null: false
end
end
\ No newline at end of file
class AddDashboardToUsers < ActiveRecord::Migration
def up
add_column :users, :dashboard, :integer, default: 0
end
def down
remove_column :users, :dashboard
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150609125332) do
ActiveRecord::Schema.define(version: 20150610065936) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -40,13 +40,14 @@ ActiveRecord::Schema.define(version: 20150609125332) do
t.boolean "twitter_sharing_enabled", default: true
t.text "help_text"
t.text "restricted_visibility_levels"
t.integer "max_attachment_size", default: 10, null: false
t.boolean "version_check_enabled", default: true
t.integer "max_attachment_size", default: 10, null: false
t.integer "default_project_visibility"
t.integer "default_snippet_visibility"
t.text "restricted_signup_domains"
t.boolean "version_check_enabled", default: true
t.boolean "user_oauth_applications", default: true
t.string "after_sign_out_path"
t.integer "session_expire_delay", default: 10080, null: false
end
create_table "approvals", force: true do |t|
......@@ -579,12 +580,13 @@ ActiveRecord::Schema.define(version: 20150609125332) do
t.string "bitbucket_access_token"
t.string "bitbucket_access_token_secret"
t.string "location"
t.string "public_email", default: "", null: false
t.string "encrypted_otp_secret"
t.string "encrypted_otp_secret_iv"
t.string "encrypted_otp_secret_salt"
t.boolean "otp_required_for_login"
t.text "otp_backup_codes"
t.string "public_email", default: "", null: false
t.integer "dashboard", default: 0
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
......@@ -3,35 +3,36 @@
## User documentation
- [API](api/README.md) Automate GitLab via a simple and powerful API.
- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
- [Importing to GitLab](workflow/importing/README.md).
- [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
- [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do.
- [Profile Settings](profile/README.md)
- [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
- [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
## Administrator documentation
- [Install](install/README.md) Requirements, directory structures and installation from source.
- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter.
- [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
- [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough.
- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
- [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
- [Update](update/README.md) Update guides to upgrade your installation.
- [Audit Events](administration/audit_events.md) Check how user access changed in projects and groups.
- [Changing the appearance of the login page](customization/branded_login_page.md) Make the login page branded for your GitLab instance.
- [Help message](customization/help_message.md) Set information about administrators of your GitLab instance.
- [Git Hooks](git_hooks/git_hooks.md) Advanced push rules for your project.
- [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough.
- [Email](tools/email.md) Email GitLab users from GitLab
- [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
- [Git Hooks](git_hooks/git_hooks.md) Advanced push rules for your project.
- [Help message](customization/help_message.md) Set information about administrators of your GitLab instance.
- [Install](install/README.md) Requirements, directory structures and installation from source.
- [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter.
- [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
- [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
- [Log system](logs/logs.md) Log system.
- [Operations](operations/README.md) Keeping GitLab up and running
- [Log system](logs/logs.md) Log system
- [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
- [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
- [Update](update/README.md) Update guides to upgrade your installation.
- [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
## Contributor documentation
......
......@@ -4,6 +4,9 @@ Sometimes it is useful to import the database from a production environment
into a staging environment for testing. The procedure below assumes you have
SSH+sudo access to both the production environment and the staging VM.
**Destroy your staging VM** when you are done with it. It is important to avoid
data leaks.
On the staging VM, add the following line to `/etc/gitlab/gitlab.rb` to speed up
large database imports.
......@@ -12,6 +15,8 @@ large database imports.
echo "postgresql['checkpoint_segments'] = 64" | sudo tee -a /etc/gitlab/gitlab.rb
sudo touch /etc/gitlab/skip-auto-migrations
sudo gitlab-ctl reconfigure
sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq
```
Next, we let the production environment stream a compressed SQL dump to our
......
......@@ -177,3 +177,33 @@ File.open(full_path) do # Etc.
```
A check like this could have avoided CVE-2013-4583.
## Properly anchor regular expressions to the start and end of strings
When using regular expressions to validate user input that is passed as an argument to a shell command, make sure to use the `\A` and `\z` anchors that designate the start and end of the string, rather than `^` and `$`, or no anchors at all.
If you don't, an attacker could use this to execute commands with potentially harmful effect.
For example, when a project's `import_url` is validated like below, the user could trick GitLab into cloning from a Git repository on the local filesystem.
```ruby
validates :import_url, format: { with: URI.regexp(%w(ssh git http https)) }
# URI.regexp(%w(ssh git http https)) roughly evaluates to /(ssh|git|http|https):(something_that_looks_like_a_url)/
```
Suppose the user submits the following as their import URL:
```
file://git:/tmp/lol
```
Since there are no anchors in the used regular expression, the `git:/tmp/lol` in the value would match, and the validation would pass.
When importing, GitLab would execute the following command, passing the `import_url` as an argument:
```sh
git clone file://git:/tmp/lol
```
Git would simply ignore the `git:` part, interpret the path as `file:///tmp/lol` and import the repository into the new project, in turn potentially giving the attacker access to any repository in the system, whether private or not.
......@@ -88,8 +88,8 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source
cd /tmp
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.1.2.tar.gz | tar xz
cd git-2.1.2/
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.4.3.tar.gz | tar xz
cd git-2.4.3/
./configure
make prefix=/usr/local all
......@@ -195,9 +195,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-11-stable gitlab
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-12-stable gitlab
**Note:** You can change `7-11-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `7-12-stable-ee` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......
# Profile Settings
- [Preferences](preferences.md)
- [Two-factor Authentication (2FA)](two_factor_authentication.md)
# Profile Preferences
Settings in the **Profile > Preferences** page allow the user to customize
various aspects of the site to their liking.
## Application theme
Changing this setting allows the user to customize the color scheme used for the
navigation bar on the left side of the screen.
The default is **Charcoal**.
## Syntax highlighting theme
Changing this setting allows the user to customize the theme used when viewing
syntax highlighted code on the site.
The default is **White**.
## Behavior
### Default Dashboard
For users who have access to a large number of projects but only keep up with a
select few, the amount of activity on the default Dashboard page can be
overwhelming.
Changing this setting allows the user to redefine what their default dashboard
will be. Setting it to **Starred Projects** will make that Dashboard view the
default when signing in or clicking the application logo in the upper left.
The default is **Your Projects**.
......@@ -4,7 +4,7 @@ GitLab provides a way to push update messages to an Irker server. When
configured, pushes to a project will trigger the service to send data directly
to the Irker server.
See the project homepage for further info: http://www.catb.org/esr/irker/
See the project homepage for further info: https://gitlab.com/esr/irker
## Needed setup
......
......@@ -30,9 +30,6 @@ All steps from issue template are explained below
```
Xth: (7 working days before the 22nd)
- [ ] Update the CE changelog (#LINK)
- [ ] Update the EE changelog (#LINK)
- [ ] Update the CI changelog (#LINK)
- [ ] Triage the omnibus-gitlab milestone
Xth: (6 working days before the 22nd)
......@@ -41,6 +38,7 @@ Xth: (6 working days before the 22nd)
- [ ] Determine QA person and notify this person
- [ ] Check the tasks in [how to rc1 guide](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/release/howto_rc1.md) and delegate tasks if necessary
- [ ] Create CE, EE, CI RC1 versions (#LINK)
- [ ] Build RC1 packages (EE first) (#LINK)
Xth: (5 working days before the 22nd)
......@@ -142,7 +140,8 @@ Tweet about the RC release:
## Prepare the blog post
1. Start with a complete copy of the [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) and fill it out.
1. The blog post template for this release should already exist and might have comments that were added during the month.
1. Fill out as much of the blog post template as you can.
1. Make sure the blog post contains information about the GitLab CI release.
1. Check the changelog of CE and EE for important changes.
1. Also check the CI changelog
......@@ -155,6 +154,7 @@ Tweet about the RC release:
1. Create a merge request on [GitLab.com](https://gitlab.com/gitlab-com/www-gitlab-com/tree/master)
1. Assign to one reviewer who will fix spelling issues by editing the branch (either with a git client or by using the online editor)
1. Comment to the reviewer: '@person Please mention the whole team as soon as you are done (3 workdays before release at the latest)'
1. Create a complete copy of the [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md) for the release after this.
## Create CE, EE, CI stable versions
......@@ -212,4 +212,4 @@ Consider creating a post on Hacker News.
## Create a WIP blogpost for the next release
Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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