Commit 26d862fa authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'upstream-ce' into 'master'

Pull 7.1.0.pre from Community Edition

See merge request !126
parents efd08747 f5285d31
...@@ -7,6 +7,19 @@ v 7.1.0 ...@@ -7,6 +7,19 @@ v 7.1.0
- Add @all mention for comments - Add @all mention for comments
- Dont show reply button if user is not signed in - Dont show reply button if user is not signed in
- Expose more information for issues with webhook - Expose more information for issues with webhook
- Add a mention of the merge request into the default merge request commit message
- Imrpove code highlight, introduce support for more languages like Go, Clojure, Erlang etc
- Fix concurrency issue in repository download
- Dont allow repository name start with ?
- Improve email threading (Pierre de La Morinerie)
- Cleaner help page
- Group milestones
- Improved email notifications
- Contributors API (sponsored by Mobbr)
- Fix LDAP TLS authentication (Boris HUISGEN)
- Show VERSION information on project sidebar
- Improve branch removal logic when accept MR
- Fix bug where comment form is spawned inside the Reply button
v 7.0.0 v 7.0.0
- The CPU no longer overheats when you hold down the spacebar - The CPU no longer overheats when you hold down the spacebar
......
...@@ -42,7 +42,7 @@ Please send a merge request with a tested solution or a merge request with a fai ...@@ -42,7 +42,7 @@ Please send a merge request with a tested solution or a merge request with a fai
1. **Observed behavior** 1. **Observed behavior**
1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise. 1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise.
1. **Output of checks** 1. **Output of checks**
* Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production`); we will only investigate if the tests are passing * Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing
* Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md) * Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md)
* Add the last commit sha1 of the GitLab version you used to replicate the issue (obtainable from the help page) * Add the last commit sha1 of the GitLab version you used to replicate the issue (obtainable from the help page)
* Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`) * Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
......
...@@ -10,8 +10,6 @@ end ...@@ -10,8 +10,6 @@ end
gem "rails", "~> 4.1.0" gem "rails", "~> 4.1.0"
gem "protected_attributes"
# Make links from text # Make links from text
gem 'rails_autolink', '~> 1.1' gem 'rails_autolink', '~> 1.1'
...@@ -23,8 +21,8 @@ gem "mysql2", group: :mysql ...@@ -23,8 +21,8 @@ gem "mysql2", group: :mysql
gem "pg", group: :postgres gem "pg", group: :postgres
# Auth # Auth
gem "devise", '3.0.4' gem "devise", '3.2.4'
gem "devise-async", '0.8.0' gem "devise-async", '0.9.0'
gem 'omniauth', "~> 1.1.3" gem 'omniauth', "~> 1.1.3"
gem 'omniauth-google-oauth2' gem 'omniauth-google-oauth2'
gem 'omniauth-twitter' gem 'omniauth-twitter'
...@@ -49,7 +47,6 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist" ...@@ -49,7 +47,6 @@ gem "gitlab-linguist", "~> 3.0.0", require: "linguist"
# API # API
gem "grape", "~> 0.6.1" gem "grape", "~> 0.6.1"
# Replace with rubygems when nesteted entities get released
gem "grape-entity", "~> 0.4.2" gem "grape-entity", "~> 0.4.2"
gem 'rack-cors', require: 'rack/cors' gem 'rack-cors', require: 'rack/cors'
......
...@@ -40,7 +40,7 @@ GEM ...@@ -40,7 +40,7 @@ GEM
axiom-types (0.0.5) axiom-types (0.0.5)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
ice_nine (~> 0.9) ice_nine (~> 0.9)
bcrypt-ruby (3.1.2) bcrypt (3.1.7)
better_errors (1.0.1) better_errors (1.0.1)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubis (>= 2.6.6) erubis (>= 2.6.6)
...@@ -94,13 +94,14 @@ GEM ...@@ -94,13 +94,14 @@ GEM
default_value_for (3.0.0) default_value_for (3.0.0)
activerecord (>= 3.2.0, < 5.0) activerecord (>= 3.2.0, < 5.0)
descendants_tracker (0.0.3) descendants_tracker (0.0.3)
devise (3.0.4) devise (3.2.4)
bcrypt-ruby (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5) railties (>= 3.2.6, < 5)
thread_safe (~> 0.1)
warden (~> 1.2.3) warden (~> 1.2.3)
devise-async (0.8.0) devise-async (0.9.0)
devise (>= 2.2, < 3.2) devise (~> 3.2)
diff-lcs (1.2.5) diff-lcs (1.2.5)
diffy (3.0.3) diffy (3.0.3)
docile (1.1.1) docile (1.1.1)
...@@ -175,7 +176,7 @@ GEM ...@@ -175,7 +176,7 @@ GEM
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.0.1.1) gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1) emoji (~> 1.0.1)
gitlab_git (6.0.0) gitlab_git (6.0.1)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-grit (~> 2.6) gitlab-grit (~> 2.6)
...@@ -282,7 +283,7 @@ GEM ...@@ -282,7 +283,7 @@ GEM
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mini_portile (0.6.0) mini_portile (0.6.0)
minitest (5.3.4) minitest (5.3.5)
multi_json (1.10.1) multi_json (1.10.1)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (1.2.0) multipart-post (1.2.0)
...@@ -331,8 +332,6 @@ GEM ...@@ -331,8 +332,6 @@ GEM
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.4) polyglot (0.3.4)
posix-spawn (0.3.8) posix-spawn (0.3.8)
protected_attributes (1.0.5)
activemodel (>= 4.0.1, < 5.0)
pry (0.9.12.4) pry (0.9.12.4)
coderay (~> 1.0) coderay (~> 1.0)
method_source (~> 0.8) method_source (~> 0.8)
...@@ -586,8 +585,8 @@ DEPENDENCIES ...@@ -586,8 +585,8 @@ DEPENDENCIES
d3_rails (~> 3.1.4) d3_rails (~> 3.1.4)
database_cleaner database_cleaner
default_value_for (~> 3.0.0) default_value_for (~> 3.0.0)
devise (= 3.0.4) devise (= 3.2.4)
devise-async (= 0.8.0) devise-async (= 0.9.0)
diffy (~> 3.0.3) diffy (~> 3.0.3)
dropzonejs-rails dropzonejs-rails
email_spec email_spec
...@@ -636,7 +635,6 @@ DEPENDENCIES ...@@ -636,7 +635,6 @@ DEPENDENCIES
org-ruby org-ruby
pg pg
poltergeist (~> 1.5.1) poltergeist (~> 1.5.1)
protected_attributes
pry pry
quiet_assets (~> 1.0.1) quiet_assets (~> 1.0.1)
rack-attack rack-attack
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#= require g.raphael-min #= require g.raphael-min
#= require g.bar-min #= require g.bar-min
#= require branch-graph #= require branch-graph
#= require highlightjs.min #= require highlight.pack
#= require ace/ace #= require ace/ace
#= require d3 #= require d3
#= require underscore #= require underscore
......
...@@ -376,7 +376,7 @@ class Notes ...@@ -376,7 +376,7 @@ class Notes
### ###
replyToDiscussionNote: (e) => replyToDiscussionNote: (e) =>
form = $(".js-new-note-form") form = $(".js-new-note-form")
replyLink = $(e.target) replyLink = $(e.target).closest(".js-discussion-reply-button")
replyLink.hide() replyLink.hide()
# insert the form after the button # insert the form after the button
......
...@@ -152,16 +152,16 @@ ...@@ -152,16 +152,16 @@
} }
&.btn-close { &.btn-close {
color: #B94A48; color: $bg_danger;
font-weight: bold; border-color: $border_danger;
&:hover { &:hover {
color: #B94A48; color: #B94A48;
} }
} }
&.btn-reopen { &.btn-reopen {
color: #468847; color: $bg_success;
font-weight: bold; border-color: $border_success;
&:hover { &:hover {
color: #468847; color: #468847;
} }
......
...@@ -177,10 +177,18 @@ li.commit { ...@@ -177,10 +177,18 @@ li.commit {
.commit-row-description { .commit-row-description {
font-size: 14px; font-size: 14px;
border-left: 1px solid #e5e5e5; border-left: 1px solid #EEE;
padding: 0 15px 0 7px; padding: 10px 15px;
margin: 5px 0 10px 5px; margin: 5px 0 10px 5px;
background: #f9f9f9;
display: none; display: none;
pre {
border: none;
background: inherit;
padding: 0;
margin: 0;
}
} }
.commit-row-info { .commit-row-info {
......
...@@ -7,3 +7,7 @@ ...@@ -7,3 +7,7 @@
.member-search-form { .member-search-form {
float: left; float: left;
} }
.milestone-row {
@include str-truncated(90%);
}
...@@ -53,13 +53,9 @@ header { ...@@ -53,13 +53,9 @@ header {
font-size: 18px; font-size: 18px;
.app_logo { margin-left: -15px; } .app_logo { margin-left: -15px; }
.title { .title {
display: inline-block; @include str-truncated(70%);
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: 70%;
} }
.navbar-collapse { .navbar-collapse {
...@@ -130,6 +126,7 @@ header { ...@@ -130,6 +126,7 @@ header {
margin: 0; margin: 0;
margin-left: 5px; margin-left: 5px;
@include header-font; @include header-font;
@include str-truncated(37%);
} }
.profile-pic { .profile-pic {
...@@ -254,7 +251,7 @@ header { ...@@ -254,7 +251,7 @@ header {
.search .search-input { .search .search-input {
width: 300px; width: 300px;
&:focus { &:focus {
width: 400px; width: 330px;
} }
} }
...@@ -262,7 +259,7 @@ header { ...@@ -262,7 +259,7 @@ header {
.search .search-input { .search .search-input {
width: 200px; width: 200px;
&:focus { &:focus {
width: 300px; width: 230px;
} }
} }
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
} }
td { td {
border-color: #F1F1F1 !important; border-color: #F1F1F1 !important;
border-bottom: 1px solid;
} }
&:hover { &:hover {
td { td {
......
...@@ -6,7 +6,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -6,7 +6,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
end end
def create def create
@broadcast_message = BroadcastMessage.new(params[:broadcast_message]) @broadcast_message = BroadcastMessage.new(broadcast_message_params)
if @broadcast_message.save if @broadcast_message.save
redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully created.' redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully created.'
...@@ -29,4 +29,11 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -29,4 +29,11 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
def broadcast_messages def broadcast_messages
@broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page]) @broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page])
end end
def broadcast_message_params
params.require(:broadcast_message).permit(
:alert_type, :color, :ends_at, :font,
:message, :starts_at
)
end
end end
...@@ -20,7 +20,7 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -20,7 +20,7 @@ class Admin::GroupsController < Admin::ApplicationController
end end
def create def create
@group = Group.new(params[:group]) @group = Group.new(group_params)
@group.path = @group.name.dup.parameterize if @group.name @group.path = @group.name.dup.parameterize if @group.name
if @group.save if @group.save
...@@ -32,7 +32,7 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -32,7 +32,7 @@ class Admin::GroupsController < Admin::ApplicationController
end end
def update def update
if @group.update_attributes(params[:group]) if @group.update_attributes(group_params)
redirect_to [:admin, @group], notice: 'Group was successfully updated.' redirect_to [:admin, @group], notice: 'Group was successfully updated.'
else else
render "edit" render "edit"
...@@ -56,4 +56,8 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -56,4 +56,8 @@ class Admin::GroupsController < Admin::ApplicationController
def group def group
@group = Group.find_by(path: params[:id]) @group = Group.find_by(path: params[:id])
end end
def group_params
params.require(:group).permit(:name, :description, :path, :avatar)
end
end end
...@@ -5,7 +5,7 @@ class Admin::HooksController < Admin::ApplicationController ...@@ -5,7 +5,7 @@ class Admin::HooksController < Admin::ApplicationController
end end
def create def create
@hook = SystemHook.new(params[:hook]) @hook = SystemHook.new(hook_params)
if @hook.save if @hook.save
redirect_to admin_hooks_path, notice: 'Hook was successfully created.' redirect_to admin_hooks_path, notice: 'Hook was successfully created.'
...@@ -37,4 +37,8 @@ class Admin::HooksController < Admin::ApplicationController ...@@ -37,4 +37,8 @@ class Admin::HooksController < Admin::ApplicationController
redirect_to :back redirect_to :back
end end
def hook_params
params.require(:hook).permit(:url)
end
end end
...@@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -13,7 +13,7 @@ class Admin::UsersController < Admin::ApplicationController
end end
def new def new
@user = User.build_user @user = User.new
end end
def edit def edit
...@@ -37,15 +37,12 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -37,15 +37,12 @@ class Admin::UsersController < Admin::ApplicationController
end end
def create def create
admin = params[:user].delete("admin")
opts = { opts = {
force_random_password: true, force_random_password: true,
password_expires_at: Time.now password_expires_at: Time.now
} }
@user = User.build_user(params[:user].merge(opts), as: :admin) @user = User.new(user_params.merge(opts))
@user.admin = (admin && admin.to_i > 0)
@user.created_by_id = current_user.id @user.created_by_id = current_user.id
@user.generate_password @user.generate_password
@user.skip_confirmation! @user.skip_confirmation!
...@@ -62,19 +59,15 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -62,19 +59,15 @@ class Admin::UsersController < Admin::ApplicationController
end end
def update def update
admin = params[:user].delete("admin") if params[:user][:password].present?
user_params.merge(
if params[:user][:password].blank? password: params[:user][:password],
params[:user].delete(:password) password_confirmation: params[:user][:password_confirmation],
params[:user].delete(:password_confirmation) )
end
if admin.present?
user.admin = !admin.to_i.zero?
end end
respond_to do |format| respond_to do |format|
if user.update_attributes(params[:user], as: :admin) if user.update_attributes(user_params)
user.confirm! user.confirm!
format.html { redirect_to [:admin, user], notice: 'User was successfully updated.' } format.html { redirect_to [:admin, user], notice: 'User was successfully updated.' }
format.json { head :ok } format.json { head :ok }
...@@ -115,4 +108,13 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -115,4 +108,13 @@ class Admin::UsersController < Admin::ApplicationController
def user def user
@user ||= User.find_by!(username: params[:id]) @user ||= User.find_by!(username: params[:id])
end end
def user_params
params.require(:user).permit(
:email, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key,
:projects_limit, :can_create_group, :admin
)
end
end end
require 'gon' require 'gon'
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
before_filter :authenticate_user_from_token!
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :reject_blocked! before_filter :reject_blocked!
before_filter :check_password_expiration before_filter :check_password_expiration
...@@ -28,6 +29,25 @@ class ApplicationController < ActionController::Base ...@@ -28,6 +29,25 @@ class ApplicationController < ActionController::Base
protected protected
# From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
# https://gist.github.com/josevalim/fb706b1e933ef01e4fb6
def authenticate_user_from_token!
user_token = if params[:authenticity_token].presence
params[:authenticity_token].presence
elsif params[:private_token].presence
params[:private_token].presence
end
user = user_token && User.find_by_authentication_token(user_token.to_s)
if user
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
# sign in token, you can simply remove store: false.
sign_in user, store: false
end
end
def log_exception(exception) def log_exception(exception)
application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace
application_trace.map!{ |t| " #{t}\n" } application_trace.map!{ |t| " #{t}\n" }
...@@ -227,8 +247,7 @@ class ApplicationController < ActionController::Base ...@@ -227,8 +247,7 @@ class ApplicationController < ActionController::Base
end end
def configure_permitted_parameters def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me) } devise_parameter_sanitizer.sanitize(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :name, :password, :password_confirmation) }
end end
def hexdigest(string) def hexdigest(string)
......
class Groups::MilestonesController < ApplicationController
layout 'group'
before_filter :authorize_group_milestone!, only: :update
def index
project_milestones = case params[:status]
when 'all'; status
when 'closed'; status('closed')
else status('active')
end
@group_milestones = Milestones::GroupService.new(project_milestones).execute
@group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(30)
end
def show
project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
@group_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
end
def update
project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
@group_milestones = Milestones::GroupService.new(project_milestones).milestone(title)
@group_milestones.milestones.each do |milestone|
Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone)
end
respond_to do |format|
format.js
format.html do
redirect_to group_milestones_path(group)
end
end
end
private
def group
@group ||= Group.find_by(path: params[:group_id])
end
def title
params[:title]
end
def status(state = nil)
conditions = { project_id: group.projects }
conditions.reverse_merge!(state: state) if state
Milestone.where(conditions).order("title ASC")
end
def authorize_group_milestone!
return render_404 unless can?(current_user, :manage_group, group)
end
end
...@@ -22,7 +22,7 @@ class GroupsController < ApplicationController ...@@ -22,7 +22,7 @@ class GroupsController < ApplicationController
end end
def create def create
@group = Group.new(params[:group]) @group = Group.new(group_params)
@group.path = @group.name.dup.parameterize if @group.name @group.path = @group.name.dup.parameterize if @group.name
if @group.save if @group.save
...@@ -86,7 +86,7 @@ class GroupsController < ApplicationController ...@@ -86,7 +86,7 @@ class GroupsController < ApplicationController
end end
def update def update
if @group.update_attributes(params[:group]) if @group.update_attributes(group_params)
redirect_to edit_group_path(@group), notice: 'Group was successfully updated.' redirect_to edit_group_path(@group), notice: 'Group was successfully updated.'
else else
render action: "edit" render action: "edit"
...@@ -161,4 +161,8 @@ class GroupsController < ApplicationController ...@@ -161,4 +161,8 @@ class GroupsController < ApplicationController
params[:state] = 'opened' if params[:state].blank? params[:state] = 'opened' if params[:state].blank?
params[:group_id] = @group.id params[:group_id] = @group.id
end end
def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :ldap_access, :ldap_cn)
end
end end
...@@ -7,7 +7,7 @@ class Profiles::EmailsController < ApplicationController ...@@ -7,7 +7,7 @@ class Profiles::EmailsController < ApplicationController
end end
def create def create
@email = current_user.emails.new(params[:email]) @email = current_user.emails.new(email_params)
flash[:alert] = @email.errors.full_messages.first unless @email.save flash[:alert] = @email.errors.full_messages.first unless @email.save
...@@ -23,4 +23,10 @@ class Profiles::EmailsController < ApplicationController ...@@ -23,4 +23,10 @@ class Profiles::EmailsController < ApplicationController
format.js { render nothing: true } format.js { render nothing: true }
end end
end end
private
def email_params
params.require(:email).permit(:email)
end
end end
...@@ -15,7 +15,7 @@ class Profiles::KeysController < ApplicationController ...@@ -15,7 +15,7 @@ class Profiles::KeysController < ApplicationController
end end
def create def create
@key = current_user.keys.new(params[:key]) @key = current_user.keys.new(key_params)
if @key.save if @key.save
redirect_to profile_key_path(@key) redirect_to profile_key_path(@key)
...@@ -53,4 +53,9 @@ class Profiles::KeysController < ApplicationController ...@@ -53,4 +53,9 @@ class Profiles::KeysController < ApplicationController
end end
end end
private
def key_params
params.require(:key).permit(:title, :key)
end
end end
...@@ -11,8 +11,8 @@ class Profiles::PasswordsController < ApplicationController ...@@ -11,8 +11,8 @@ class Profiles::PasswordsController < ApplicationController
end end
def create def create
new_password = params[:user][:password] new_password = user_params[:password]
new_password_confirmation = params[:user][:password_confirmation] new_password_confirmation = user_params[:password_confirmation]
result = @user.update_attributes( result = @user.update_attributes(
password: new_password, password: new_password,
...@@ -31,11 +31,11 @@ class Profiles::PasswordsController < ApplicationController ...@@ -31,11 +31,11 @@ class Profiles::PasswordsController < ApplicationController
end end
def update def update
password_attributes = params[:user].select do |key, value| password_attributes = user_params.select do |key, value|
%w(password password_confirmation).include?(key.to_s) %w(password password_confirmation).include?(key.to_s)
end end
unless @user.valid_password?(params[:user][:current_password]) unless @user.valid_password?(user_params[:current_password])
redirect_to edit_profile_password_path, alert: 'You must provide a valid current password' redirect_to edit_profile_password_path, alert: 'You must provide a valid current password'
return return
end end
...@@ -74,4 +74,8 @@ class Profiles::PasswordsController < ApplicationController ...@@ -74,4 +74,8 @@ class Profiles::PasswordsController < ApplicationController
def authorize_change_password! def authorize_change_password!
return render_404 if @user.ldap_user? return render_404 if @user.ldap_user?
end end
def user_params
params.require(:user).permit(:current_password, :password, :password_confirmation)
end
end end
...@@ -14,9 +14,9 @@ class ProfilesController < ApplicationController ...@@ -14,9 +14,9 @@ class ProfilesController < ApplicationController
end end
def update def update
params[:user].delete(:email) if @user.ldap_user? user_params.except!(:email) if @user.ldap_user?
if @user.update_attributes(params[:user]) if @user.update_attributes(user_params)
flash[:notice] = "Profile was successfully updated" flash[:notice] = "Profile was successfully updated"
else else
flash[:alert] = "Failed to update profile" flash[:alert] = "Failed to update profile"
...@@ -41,7 +41,7 @@ class ProfilesController < ApplicationController ...@@ -41,7 +41,7 @@ class ProfilesController < ApplicationController
end end
def update_username def update_username
@user.update_attributes(username: params[:user][:username]) @user.update_attributes(username: user_params[:username])
respond_to do |format| respond_to do |format|
format.js format.js
...@@ -57,4 +57,12 @@ class ProfilesController < ApplicationController ...@@ -57,4 +57,12 @@ class ProfilesController < ApplicationController
def authorize_change_username! def authorize_change_username!
return render_404 unless @user.can_change_username? return render_404 unless @user.can_change_username?
end end
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,
)
end
end end
...@@ -30,8 +30,12 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -30,8 +30,12 @@ class Projects::BlobController < Projects::ApplicationController
def blob def blob
@blob ||= @repository.blob_at(@commit.id, @path) @blob ||= @repository.blob_at(@commit.id, @path)
return not_found! unless @blob if @blob
@blob @blob
elsif tree.entries.any?
redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
else
return not_found!
end
end end
end end
...@@ -22,7 +22,7 @@ class Projects::DeployKeysController < Projects::ApplicationController ...@@ -22,7 +22,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
end end
def create def create
@key = DeployKey.new(params[:deploy_key]) @key = DeployKey.new(deploy_key_params)
if @key.valid? && @project.deploy_keys << @key if @key.valid? && @project.deploy_keys << @key
redirect_to project_deploy_keys_path(@project) redirect_to project_deploy_keys_path(@project)
...@@ -58,4 +58,8 @@ class Projects::DeployKeysController < Projects::ApplicationController ...@@ -58,4 +58,8 @@ class Projects::DeployKeysController < Projects::ApplicationController
def available_keys def available_keys
@available_keys ||= current_user.accessible_deploy_keys @available_keys ||= current_user.accessible_deploy_keys
end end
def deploy_key_params
params.require(:deploy_key).permit(:key, :title)
end
end end
...@@ -28,8 +28,6 @@ class Projects::EditTreeController < Projects::BaseTreeController ...@@ -28,8 +28,6 @@ class Projects::EditTreeController < Projects::BaseTreeController
def preview def preview
@content = params[:content] @content = params[:content]
#FIXME workaround https://github.com/gitlabhq/gitlabhq/issues/5936
@content += "\n" if @blob.data.end_with?("\n")
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
include_diff_info: true) include_diff_info: true)
......
...@@ -14,7 +14,7 @@ class Projects::GitHooksController < Projects::ApplicationController ...@@ -14,7 +14,7 @@ class Projects::GitHooksController < Projects::ApplicationController
def update def update
@pre_receive_hook = project.git_hook @pre_receive_hook = project.git_hook
@pre_receive_hook.update_attributes(params[:git_hook]) @pre_receive_hook.update_attributes(git_hook_params)
if @pre_receive_hook.valid? if @pre_receive_hook.valid?
redirect_to project_git_hooks_path(@project) redirect_to project_git_hooks_path(@project)
...@@ -22,4 +22,11 @@ class Projects::GitHooksController < Projects::ApplicationController ...@@ -22,4 +22,11 @@ class Projects::GitHooksController < Projects::ApplicationController
render :index render :index
end end
end end
private
# Only allow a trusted parameter "white list" through.
def git_hook_params
params.require(:git_hook).permit(:deny_delete_tag, :delete_branch_regex, :commit_message_regex, :force_push_regex)
end
end end
...@@ -12,7 +12,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -12,7 +12,7 @@ class Projects::HooksController < Projects::ApplicationController
end end
def create def create
@hook = @project.hooks.new(params[:hook]) @hook = @project.hooks.new(hook_params)
@hook.save @hook.save
if @hook.valid? if @hook.valid?
...@@ -40,4 +40,8 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -40,4 +40,8 @@ class Projects::HooksController < Projects::ApplicationController
def hook def hook
@hook ||= @project.hooks.find(params[:id]) @hook ||= @project.hooks.find(params[:id])
end end
def hook_params
params.require(:hook).permit(:url, :push_events, :issues_events, :merge_requests_events, :tag_push_events)
end
end end
...@@ -42,7 +42,11 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -42,7 +42,11 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def new def new
@issue = @project.issues.new(params[:issue]) params[:issue] ||= ActionController::Parameters.new(
assignee_id: ""
)
@issue = @project.issues.new(issue_params)
respond_with(@issue) respond_with(@issue)
end end
...@@ -59,7 +63,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -59,7 +63,7 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def create def create
@issue = Issues::CreateService.new(project, current_user, params[:issue]).execute @issue = Issues::CreateService.new(project, current_user, issue_params).execute
respond_to do |format| respond_to do |format|
format.html do format.html do
...@@ -76,7 +80,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -76,7 +80,7 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def update def update
@issue = Issues::UpdateService.new(project, current_user, params[:issue]).execute(issue) @issue = Issues::UpdateService.new(project, current_user, issue_params).execute(issue)
respond_to do |format| respond_to do |format|
format.js format.js
...@@ -144,4 +148,11 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -144,4 +148,11 @@ class Projects::IssuesController < Projects::ApplicationController
raise ActiveRecord::RecordNotFound.new raise ActiveRecord::RecordNotFound.new
end end
end end
def issue_params
params.require(:issue).permit(
:title, :assignee_id, :position, :description,
:milestone_id, :label_list, :state_event
)
end
end end
...@@ -60,7 +60,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -60,7 +60,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def new def new
@merge_request = MergeRequest.new(params[:merge_request]) params[:merge_request] ||= ActionController::Parameters.new(
source_project: @project
)
@merge_request = MergeRequest.new(merge_request_params)
@merge_request.source_project = @project unless @merge_request.source_project @merge_request.source_project = @project unless @merge_request.source_project
@merge_request.target_project ||= (@project.forked_from_project || @project) @merge_request.target_project ||= (@project.forked_from_project || @project)
@target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names @target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names
...@@ -111,7 +115,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -111,7 +115,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def create def create
@target_branches ||= [] @target_branches ||= []
@merge_request = MergeRequests::CreateService.new(project, current_user, params[:merge_request]).execute @merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute
if @merge_request.valid? if @merge_request.valid?
redirect_to project_merge_request_path(@merge_request.target_project, @merge_request), notice: 'Merge request was successfully created.' redirect_to project_merge_request_path(@merge_request.target_project, @merge_request), notice: 'Merge request was successfully created.'
...@@ -123,7 +127,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -123,7 +127,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def update def update
@merge_request = MergeRequests::UpdateService.new(project, current_user, params[:merge_request]).execute(@merge_request) @merge_request = MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request)
if @merge_request.valid? if @merge_request.valid?
respond_to do |format| respond_to do |format|
...@@ -264,4 +268,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -264,4 +268,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
can?(current_user, action, project) can?(current_user, action, project)
end end
def merge_request_params
params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id,
:state_event, :description, :label_list
)
end
end end
...@@ -37,7 +37,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -37,7 +37,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def create def create
@milestone = Milestones::CreateService.new(project, current_user, params[:milestone]).execute @milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute
if @milestone.save if @milestone.save
redirect_to project_milestone_path(@project, @milestone) redirect_to project_milestone_path(@project, @milestone)
...@@ -47,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -47,7 +47,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end end
def update def update
@milestone = Milestones::UpdateService.new(project, current_user, params[:milestone]).execute(milestone) @milestone = Milestones::UpdateService.new(project, current_user, milestone_params).execute(milestone)
respond_to do |format| respond_to do |format|
format.js format.js
...@@ -105,4 +105,8 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -105,4 +105,8 @@ class Projects::MilestonesController < Projects::ApplicationController
def module_enabled def module_enabled
return render_404 unless @project.issues_enabled return render_404 unless @project.issues_enabled
end end
def milestone_params
params.require(:milestone).permit(:title, :description, :due_date, :state_event)
end
end end
...@@ -21,7 +21,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -21,7 +21,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def create def create
@note = Notes::CreateService.new(project, current_user, params[:note]).execute @note = Notes::CreateService.new(project, current_user, note_params).execute
respond_to do |format| respond_to do |format|
format.json { render_note_json(@note) } format.json { render_note_json(@note) }
...@@ -30,7 +30,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -30,7 +30,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def update def update
note.update_attributes(params[:note]) note.update_attributes(note_params)
note.reset_events_cache note.reset_events_cache
respond_to do |format| respond_to do |format|
...@@ -109,4 +109,11 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -109,4 +109,11 @@ class Projects::NotesController < Projects::ApplicationController
def authorize_admin_note! def authorize_admin_note!
return access_denied! unless can?(current_user, :admin_note, note) return access_denied! unless can?(current_user, :admin_note, note)
end end
def note_params
params.require(:note).permit(
:note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id
)
end
end end
...@@ -11,7 +11,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -11,7 +11,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
end end
def create def create
@project.protected_branches.create(params[:protected_branch]) @project.protected_branches.create(protected_branch_params)
redirect_to project_protected_branches_path(@project) redirect_to project_protected_branches_path(@project)
end end
...@@ -23,4 +23,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -23,4 +23,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
format.js { render nothing: true } format.js { render nothing: true }
end end
end end
private
def protected_branch_params
params.require(:protected_branch).permit(:name)
end
end end
...@@ -22,6 +22,7 @@ class Projects::RepositoriesController < Projects::ApplicationController ...@@ -22,6 +22,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
if file_path if file_path
# Send file to user # Send file to user
response.headers["Content-Length"] = File.open(file_path).size.to_s
send_file file_path send_file file_path
else else
render_404 render_404
......
...@@ -16,7 +16,7 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -16,7 +16,7 @@ class Projects::ServicesController < Projects::ApplicationController
end end
def update def update
if @service.update_attributes(params[:service]) if @service.update_attributes(service_params)
redirect_to edit_project_service_path(@project, @service.to_param) redirect_to edit_project_service_path(@project, @service.to_param)
else else
render 'edit' render 'edit'
...@@ -36,4 +36,11 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -36,4 +36,11 @@ class Projects::ServicesController < Projects::ApplicationController
def service def service
@service ||= @project.services.find { |service| service.to_param == params[:id] } @service ||= @project.services.find { |service| service.to_param == params[:id] }
end end
def service_params
params.require(:service).permit(
:title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url, :username, :password, :api_version
)
end
end end
...@@ -25,7 +25,7 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -25,7 +25,7 @@ class Projects::SnippetsController < Projects::ApplicationController
end end
def create def create
@snippet = @project.snippets.build(params[:project_snippet]) @snippet = @project.snippets.build(snippet_params)
@snippet.author = current_user @snippet.author = current_user
if @snippet.save if @snippet.save
...@@ -39,7 +39,7 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -39,7 +39,7 @@ class Projects::SnippetsController < Projects::ApplicationController
end end
def update def update
if @snippet.update_attributes(params[:project_snippet]) if @snippet.update_attributes(snippet_params)
redirect_to project_snippet_path(@project, @snippet) redirect_to project_snippet_path(@project, @snippet)
else else
respond_with(@snippet) respond_with(@snippet)
...@@ -86,4 +86,8 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -86,4 +86,8 @@ class Projects::SnippetsController < Projects::ApplicationController
def module_enabled def module_enabled
return render_404 unless @project.snippets_enabled return render_404 unless @project.snippets_enabled
end end
def snippet_params
params.require(:project_snippet).permit(:title, :content, :file_name, :private)
end
end end
...@@ -27,7 +27,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -27,7 +27,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
def update def update
@user_project_relation = project.users_projects.find_by(user_id: member) @user_project_relation = project.users_projects.find_by(user_id: member)
@user_project_relation.update_attributes(params[:team_member]) @user_project_relation.update_attributes(member_params)
unless @user_project_relation.valid? unless @user_project_relation.valid?
flash[:alert] = "User should have at least one role" flash[:alert] = "User should have at least one role"
...@@ -67,4 +67,8 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -67,4 +67,8 @@ class Projects::TeamMembersController < Projects::ApplicationController
def member def member
@member ||= User.find_by(username: params[:id]) @member ||= User.find_by(username: params[:id])
end end
def member_params
params.require(:team_member).permit(:user_id, :project_access)
end
end end
# Controller for viewing a repository's file structure # Controller for viewing a repository's file structure
class Projects::TreeController < Projects::BaseTreeController class Projects::TreeController < Projects::BaseTreeController
def show def show
return not_found! if tree.entries.empty?
if tree.entries.empty?
if @repository.blob_at(@commit.id, @path)
redirect_to project_blob_path(@project, File.join(@ref, @path)) and return
else
return not_found!
end
end
respond_to do |format| respond_to do |format|
format.html format.html
......
...@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController ...@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController
end end
def create def create
@project = ::Projects::CreateService.new(current_user, params[:project]).execute @project = ::Projects::CreateService.new(current_user, project_params).execute
flash[:notice] = 'Project was successfully created.' if @project.saved? flash[:notice] = 'Project was successfully created.' if @project.saved?
respond_to do |format| respond_to do |format|
...@@ -29,7 +29,7 @@ class ProjectsController < ApplicationController ...@@ -29,7 +29,7 @@ class ProjectsController < ApplicationController
end end
def update def update
status = ::Projects::UpdateService.new(@project, current_user, params).execute status = ::Projects::UpdateService.new(@project, current_user, project_params).execute
respond_to do |format| respond_to do |format|
if status if status
...@@ -44,7 +44,7 @@ class ProjectsController < ApplicationController ...@@ -44,7 +44,7 @@ class ProjectsController < ApplicationController
end end
def transfer def transfer
::Projects::TransferService.new(project, current_user, params[:project]).execute ::Projects::TransferService.new(project, current_user, project_params).execute
end end
def show def show
...@@ -85,7 +85,7 @@ class ProjectsController < ApplicationController ...@@ -85,7 +85,7 @@ class ProjectsController < ApplicationController
redirect_to import_project_path(@project) redirect_to import_project_path(@project)
end end
@project.import_url = params[:project][:import_url] @project.import_url = project_params[:import_url]
if @project.save if @project.save
@project.reload @project.reload
...@@ -185,4 +185,12 @@ class ProjectsController < ApplicationController ...@@ -185,4 +185,12 @@ class ProjectsController < ApplicationController
def user_layout def user_layout
current_user ? "projects" : "public_projects" current_user ? "projects" : "public_projects"
end end
def project_params
params.require(:project).permit(
:name, :path, :description, :issues_tracker, :label_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :merge_requests_template
)
end
end end
...@@ -13,7 +13,14 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -13,7 +13,14 @@ class RegistrationsController < Devise::RegistrationsController
def build_resource(hash=nil) def build_resource(hash=nil)
super super
self.resource.with_defaults end
def after_sign_up_path_for resource
new_user_session_path
end
def after_inactive_sign_up_path_for resource
new_user_session_path
end end
private private
...@@ -21,4 +28,8 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -21,4 +28,8 @@ class RegistrationsController < Devise::RegistrationsController
def signup_enabled? def signup_enabled?
redirect_to new_user_session_path unless Gitlab.config.gitlab.signup_enabled redirect_to new_user_session_path unless Gitlab.config.gitlab.signup_enabled
end end
def sign_up_params
params.require(:user).permit(:username, :email, :name, :password, :password_confirmation)
end
end end
...@@ -51,7 +51,7 @@ class SnippetsController < ApplicationController ...@@ -51,7 +51,7 @@ class SnippetsController < ApplicationController
end end
def create def create
@snippet = PersonalSnippet.new(params[:personal_snippet]) @snippet = PersonalSnippet.new(snippet_params)
@snippet.author = current_user @snippet.author = current_user
if @snippet.save if @snippet.save
...@@ -65,7 +65,7 @@ class SnippetsController < ApplicationController ...@@ -65,7 +65,7 @@ class SnippetsController < ApplicationController
end end
def update def update
if @snippet.update_attributes(params[:personal_snippet]) if @snippet.update_attributes(snippet_params)
redirect_to snippet_path(@snippet) redirect_to snippet_path(@snippet)
else else
respond_with @snippet respond_with @snippet
...@@ -109,4 +109,8 @@ class SnippetsController < ApplicationController ...@@ -109,4 +109,8 @@ class SnippetsController < ApplicationController
def set_title def set_title
@title = 'Snippets' @title = 'Snippets'
end end
def snippet_params
params.require(:personal_snippet).permit(:title, :content, :file_name, :private)
end
end end
...@@ -14,7 +14,7 @@ class UsersGroupsController < ApplicationController ...@@ -14,7 +14,7 @@ class UsersGroupsController < ApplicationController
def update def update
@member = @group.users_groups.find(params[:id]) @member = @group.users_groups.find(params[:id])
@member.update_attributes(params[:users_group]) @member.update_attributes(member_params)
end end
def destroy def destroy
...@@ -41,4 +41,8 @@ class UsersGroupsController < ApplicationController ...@@ -41,4 +41,8 @@ class UsersGroupsController < ApplicationController
return render_404 return render_404
end end
end end
def member_params
params.require(:users_group).permit(:group_access, :user_id)
end
end end
...@@ -14,7 +14,7 @@ class NotesFinder ...@@ -14,7 +14,7 @@ class NotesFinder
project.issues.find(target_id).notes.inc_author.fresh project.issues.find(target_id).notes.inc_author.fresh
when "merge_request" when "merge_request"
project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh
when "snippet" when "snippet", "project_snippet"
project.snippets.find(target_id).notes.fresh project.snippets.find(target_id).notes.fresh
else else
raise 'invalid target_type' raise 'invalid target_type'
......
...@@ -180,6 +180,17 @@ module CommitsHelper ...@@ -180,6 +180,17 @@ module CommitsHelper
return old_lines, new_lines return old_lines, new_lines
end end
def link_to_browse_code(project, commit)
if current_controller?(:projects, :commits)
if @repo.blob_at(commit.id, @path)
return link_to "Browse File »", project_blob_path(project, tree_join(commit.id, @path)), class: "pull-right"
elsif @path.present?
return link_to "Browse Dir »", project_tree_path(project, tree_join(commit.id, @path)), class: "pull-right"
end
end
link_to "Browse Code »", project_tree_path(project, commit), class: "pull-right"
end
protected protected
# Private: Returns a link to a person. If the person has a matching user and # Private: Returns a link to a person. If the person has a matching user and
......
...@@ -35,4 +35,42 @@ module DashboardHelper ...@@ -35,4 +35,42 @@ module DashboardHelper
path << "?#{options.to_param}" path << "?#{options.to_param}"
path path
end end
def assigned_entities_count(current_user, entity, scope = nil)
items = current_user.send("assigned_" + entity.pluralize).opened
if scope.kind_of?(Group)
items = items.of_group(scope)
elsif scope.kind_of?(Project)
items = items.of_projects(scope)
end
items.count
end
def authored_entities_count(current_user, entity, scope = nil)
items = current_user.send(entity.pluralize).opened
if scope.kind_of?(Group)
items = items.of_group(scope)
elsif scope.kind_of?(Project)
items = items.of_projects(scope)
end
items.count
end
def authorized_entities_count(current_user, entity, scope = nil)
items = entity.classify.constantize.opened
if scope.kind_of?(Group)
items = items.of_group(scope)
elsif scope.kind_of?(Project)
items = items.of_projects(scope)
else
items = items.of_projects(current_user.authorized_projects)
end
items.count
end
end end
...@@ -64,7 +64,16 @@ module EventsHelper ...@@ -64,7 +64,16 @@ module EventsHelper
project_issue_url(event.project, event.issue) project_issue_url(event.project, event.issue)
elsif event.merge_request? elsif event.merge_request?
project_merge_request_url(event.project, event.merge_request) project_merge_request_url(event.project, event.merge_request)
elsif event.note?
if event.note_target
if event.note_commit?
project_commit_path(event.project, event.note_commit_id, anchor: dom_id(event.target))
elsif event.note_project_snippet?
project_snippet_path(event.project, event.note_target)
else
event_note_target_path(event)
end
end
elsif event.push? elsif event.push?
if event.push_with_commits? if event.push_with_commits?
if event.commits_count > 1 if event.commits_count > 1
...@@ -83,6 +92,10 @@ module EventsHelper ...@@ -83,6 +92,10 @@ module EventsHelper
render "events/event_issue", issue: event.issue render "events/event_issue", issue: event.issue
elsif event.push? elsif event.push?
render "events/event_push", event: event render "events/event_push", event: event
elsif event.merge_request?
render "events/event_merge_request", merge_request: event.merge_request
elsif event.note?
render "events/event_note", note: event.note
end end
end end
......
...@@ -138,7 +138,7 @@ module GitlabMarkdownHelper ...@@ -138,7 +138,7 @@ module GitlabMarkdownHelper
# If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md) # If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md)
# this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md # this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md
# If we are at doc/api and the README.md shown in below the tree view # If we are at doc/api and the README.md shown in below the tree view
# this takes the rquest path(doc/api) and adds users.md so the path looks like doc/api/users.md # this takes the request path(doc/api) and adds users.md so the path looks like doc/api/users.md
def build_nested_path(path, request_path) def build_nested_path(path, request_path)
return request_path if path == "" return request_path if path == ""
return path unless request_path return path unless request_path
......
...@@ -31,6 +31,17 @@ module GroupsHelper ...@@ -31,6 +31,17 @@ module GroupsHelper
end end
title title
end
def group_filter_path(entity, options={})
exist_opts = {
status: params[:status]
}
options = exist_opts.merge(options)
path = request.path
path << "?#{options.to_param}"
path
end end
end end
...@@ -4,8 +4,8 @@ module Emails ...@@ -4,8 +4,8 @@ module Emails
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@project = @issue.project @project = @issue.project
@target_url = project_issue_url(@project, @issue) @target_url = project_issue_url(@project, @issue)
set_message_id("issue_#{issue_id}") mail_new_thread(@issue,
mail(from: sender(@issue.author_id), from: sender(@issue.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
end end
...@@ -15,8 +15,8 @@ module Emails ...@@ -15,8 +15,8 @@ module Emails
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @issue.project @project = @issue.project
@target_url = project_issue_url(@project, @issue) @target_url = project_issue_url(@project, @issue)
set_reference("issue_#{issue_id}") mail_answer_thread(@issue,
mail(from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
end end
...@@ -26,8 +26,8 @@ module Emails ...@@ -26,8 +26,8 @@ module Emails
@project = @issue.project @project = @issue.project
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue) @target_url = project_issue_url(@project, @issue)
set_reference("issue_#{issue_id}") mail_answer_thread(@issue,
mail(from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
end end
...@@ -38,8 +38,8 @@ module Emails ...@@ -38,8 +38,8 @@ module Emails
@project = @issue.project @project = @issue.project
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@target_url = project_issue_url(@project, @issue) @target_url = project_issue_url(@project, @issue)
set_reference("issue_#{issue_id}") mail_answer_thread(@issue,
mail(from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
end end
......
...@@ -4,8 +4,8 @@ module Emails ...@@ -4,8 +4,8 @@ module Emails
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request) @target_url = project_merge_request_url(@project, @merge_request)
set_message_id("merge_request_#{merge_request_id}") mail_new_thread(@merge_request,
mail(from: sender(@merge_request.author_id), from: sender(@merge_request.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end end
...@@ -15,8 +15,8 @@ module Emails ...@@ -15,8 +15,8 @@ module Emails
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request) @target_url = project_merge_request_url(@project, @merge_request)
set_reference("merge_request_#{merge_request_id}") mail_answer_thread(@merge_request,
mail(from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end end
...@@ -26,8 +26,8 @@ module Emails ...@@ -26,8 +26,8 @@ module Emails
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request) @target_url = project_merge_request_url(@project, @merge_request)
set_reference("merge_request_#{merge_request_id}") mail_answer_thread(@merge_request,
mail(from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end end
...@@ -36,10 +36,22 @@ module Emails ...@@ -36,10 +36,22 @@ module Emails
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project @project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request) @target_url = project_merge_request_url(@project, @merge_request)
mail_answer_thread(@merge_request,
from: sender(updated_by_user_id),
to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id)
@mr_status = status
@project = @merge_request.project
@updated_by = User.find updated_by_user_id
@target_url = project_merge_request_url(@project, @merge_request)
set_reference("merge_request_#{merge_request_id}") set_reference("merge_request_#{merge_request_id}")
mail(from: sender(updated_by_user_id), mail(from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid}) #{@mr_status}"))
end end
end end
......
...@@ -5,7 +5,8 @@ module Emails ...@@ -5,7 +5,8 @@ module Emails
@commit = @note.noteable @commit = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}") @target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}")
mail(from: sender(@note.author_id), mail_answer_thread(@commit,
from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@commit.title} (#{@commit.short_id})")) subject: subject("#{@commit.title} (#{@commit.short_id})"))
end end
...@@ -15,8 +16,8 @@ module Emails ...@@ -15,8 +16,8 @@ module Emails
@issue = @note.noteable @issue = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}") @target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
set_reference("issue_#{@issue.id}") mail_answer_thread(@issue,
mail(from: sender(@note.author_id), from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@issue.title} (##{@issue.iid})")) subject: subject("#{@issue.title} (##{@issue.iid})"))
end end
...@@ -26,8 +27,8 @@ module Emails ...@@ -26,8 +27,8 @@ module Emails
@merge_request = @note.noteable @merge_request = @note.noteable
@project = @note.project @project = @note.project
@target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}") @target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
set_reference("merge_request_#{@merge_request.id}") mail_answer_thread(@merge_request,
mail(from: sender(@note.author_id), from: sender(@note.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end end
......
class Notify < ActionMailer::Base class Notify < ActionMailer::Base
include ActionDispatch::Routing::PolymorphicRoutes
include Emails::Issues include Emails::Issues
include Emails::MergeRequests include Emails::MergeRequests
include Emails::Notes include Emails::Notes
...@@ -53,14 +55,6 @@ class Notify < ActionMailer::Base ...@@ -53,14 +55,6 @@ class Notify < ActionMailer::Base
end end
end end
# Set the Message-ID header field
#
# local_part - The local part of the message ID
#
def set_message_id(local_part)
headers["Message-ID"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
end
# Set the References header field # Set the References header field
# #
# local_part - The local part of the referenced message ID # local_part - The local part of the referenced message ID
...@@ -93,4 +87,40 @@ class Notify < ActionMailer::Base ...@@ -93,4 +87,40 @@ class Notify < ActionMailer::Base
subject << extra.join(' | ') if extra.present? subject << extra.join(' | ') if extra.present?
subject subject
end end
# Return a string suitable for inclusion in the 'Message-Id' mail header.
#
# The message-id is generated from the unique URL to a model object.
def message_id(model)
model_name = model.class.model_name.singular_route_key
"<#{model_name}_#{model.id}@#{Gitlab.config.gitlab.host}>"
end
# Send an email that starts a new conversation thread,
# with headers suitable for grouping by thread in email clients.
#
# See: mail_answer_thread
def mail_new_thread(model, headers = {}, &block)
headers['Message-ID'] = message_id(model)
mail(headers, &block)
end
# Send an email that responds to an existing conversation thread,
# with headers suitable for grouping by thread in email clients.
#
# For grouping emails by thread, email clients heuristics require the answers to:
#
# * have a subject that begin by 'Re: '
# * have a 'In-Reply-To' or 'References' header that references the original 'Message-ID'
#
def mail_answer_thread(model, headers = {}, &block)
headers['In-Reply-To'] = message_id(model)
headers['References'] = message_id(model)
if (headers[:subject])
headers[:subject].prepend('Re: ')
end
mail(headers, &block)
end
end end
class Appearance < ActiveRecord::Base class Appearance < ActiveRecord::Base
attr_accessible :title, :description, :logo
validates :title, presence: true validates :title, presence: true
validates :description, presence: true validates :description, presence: true
validates :logo, file_size: { maximum: 1000.kilobytes.to_i } validates :logo, file_size: { maximum: 1000.kilobytes.to_i }
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
# #
class BroadcastMessage < ActiveRecord::Base class BroadcastMessage < ActiveRecord::Base
attr_accessible :alert_type, :color, :ends_at, :font, :message, :starts_at
validates :message, presence: true validates :message, presence: true
validates :starts_at, presence: true validates :starts_at, presence: true
validates :ends_at, presence: true validates :ends_at, presence: true
......
module TokenAuthenticatable
extend ActiveSupport::Concern
module ClassMethods
def find_by_authentication_token(authentication_token = nil)
if authentication_token
where(authentication_token: authentication_token).first
end
end
end
def ensure_authentication_token
if authentication_token.blank?
self.authentication_token = generate_authentication_token
end
end
def reset_authentication_token!
self.authentication_token = generate_authentication_token
save
end
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless self.class.unscoped.where(authentication_token: token).first
end
end
end
...@@ -10,13 +10,10 @@ ...@@ -10,13 +10,10 @@
# #
class DeployKeysProject < ActiveRecord::Base class DeployKeysProject < ActiveRecord::Base
attr_accessible :key_id, :project_id
belongs_to :project belongs_to :project
belongs_to :deploy_key belongs_to :deploy_key
validates :deploy_key_id, presence: true validates :deploy_key_id, presence: true
validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" } validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
validates :project_id, presence: true validates :project_id, presence: true
end end
...@@ -10,16 +10,8 @@ ...@@ -10,16 +10,8 @@
# #
class Email < ActiveRecord::Base class Email < ActiveRecord::Base
attr_accessible :email, :user_id
#
# Relations
#
belongs_to :user belongs_to :user
#
# Validations
#
validates :user_id, presence: true validates :user_id, presence: true
validates :email, presence: true, email: { strict_mode: true }, uniqueness: true validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
validate :unique_email, if: ->(email) { email.email_changed? } validate :unique_email, if: ->(email) { email.email_changed? }
......
...@@ -15,9 +15,6 @@ ...@@ -15,9 +15,6 @@
# #
class Event < ActiveRecord::Base class Event < ActiveRecord::Base
attr_accessible :project, :action, :data, :author_id, :project_id,
:target_id, :target_type
default_scope { where.not(author_id: nil) } default_scope { where.not(author_id: nil) }
CREATED = 1 CREATED = 1
...@@ -33,6 +30,7 @@ class Event < ActiveRecord::Base ...@@ -33,6 +30,7 @@ class Event < ActiveRecord::Base
delegate :name, :email, to: :author, prefix: true, allow_nil: true delegate :name, :email, to: :author, prefix: true, allow_nil: true
delegate :title, to: :issue, prefix: true, allow_nil: true delegate :title, to: :issue, prefix: true, allow_nil: true
delegate :title, to: :merge_request, prefix: true, allow_nil: true delegate :title, to: :merge_request, prefix: true, allow_nil: true
delegate :title, to: :note, prefix: true, allow_nil: true
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
belongs_to :project belongs_to :project
...@@ -150,6 +148,10 @@ class Event < ActiveRecord::Base ...@@ -150,6 +148,10 @@ class Event < ActiveRecord::Base
target if target_type == "MergeRequest" target if target_type == "MergeRequest"
end end
def note
target if target_type == "Note"
end
def action_name def action_name
if closed? if closed?
"closed" "closed"
......
...@@ -10,10 +10,6 @@ ...@@ -10,10 +10,6 @@
# #
class ForkedProjectLink < ActiveRecord::Base class ForkedProjectLink < ActiveRecord::Base
attr_accessible :forked_from_project_id, :forked_to_project_id
# Relations
belongs_to :forked_to_project, class_name: Project belongs_to :forked_to_project, class_name: Project
belongs_to :forked_from_project, class_name: Project belongs_to :forked_from_project, class_name: Project
end end
class GitHook < ActiveRecord::Base class GitHook < ActiveRecord::Base
attr_accessible :deny_delete_tag, :delete_branch_regex, :commit_message_regex, :force_push_regex
belongs_to :project belongs_to :project
validates :project, presence: true validates :project, presence: true
......
...@@ -19,19 +19,14 @@ require 'file_size_validator' ...@@ -19,19 +19,14 @@ require 'file_size_validator'
class Group < Namespace class Group < Namespace
has_many :users_groups, dependent: :destroy has_many :users_groups, dependent: :destroy
has_many :users, through: :users_groups has_many :users, through: :users_groups
has_many :project_group_links, dependent: :destroy has_many :project_group_links, dependent: :destroy
has_many :shared_projects, through: :project_group_links, source: :project has_many :shared_projects, through: :project_group_links, source: :project
attr_accessible :ldap_cn, :ldap_access
validates :ldap_access, validates :ldap_access,
inclusion: { in: UsersGroup.group_access_roles.values }, inclusion: { in: UsersGroup.group_access_roles.values },
presence: true, presence: true,
if: ->(group) { group.ldap_cn.present? } if: ->(group) { group.ldap_cn.present? }
attr_accessible :avatar
validate :avatar_type, if: ->(user) { user.avatar_changed? } validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i } validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
......
class GroupMilestone
def initialize(title, milestones)
@title = title
@milestones = milestones
end
def title
@title
end
def safe_title
@title.parameterize
end
def milestones
@milestones
end
def projects
milestones.map { |milestone| milestone.project }
end
def issue_count
milestones.map { |milestone| milestone.issues.count }.sum
end
def merge_requests_count
milestones.map { |milestone| milestone.merge_requests.count }.sum
end
def open_items_count
milestones.map { |milestone| milestone.open_items_count }.sum
end
def closed_items_count
milestones.map { |milestone| milestone.closed_items_count }.sum
end
def total_items_count
milestones.map { |milestone| milestone.total_items_count }.sum
end
def percent_complete
((closed_items_count * 100) / total_items_count).abs
rescue ZeroDivisionError
100
end
def state
state = milestones.map { |milestone| milestone.state }
if state.count('active') == state.size
'active'
else
'closed'
end
end
def active?
state == 'active'
end
def closed?
state == 'closed'
end
def issues
@group_issues ||= milestones.map { |milestone| milestone.issues }.flatten.group_by(&:state)
end
def merge_requests
@group_merge_requests ||= milestones.map { |milestone| milestone.merge_requests }.flatten.group_by(&:state)
end
def participants
milestones.map { |milestone| milestone.participants.uniq }.reject(&:empty?).flatten
end
def opened_issues
issues.values_at("opened", "reopened").compact.flatten
end
def closed_issues
issues['closed']
end
def opened_merge_requests
merge_requests.values_at("opened", "reopened").compact.flatten
end
def closed_merge_requests
merge_requests.values_at("closed", "merged", "locked").compact.flatten
end
end
...@@ -33,9 +33,6 @@ class Issue < ActiveRecord::Base ...@@ -33,9 +33,6 @@ class Issue < ActiveRecord::Base
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) }
attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :state_event
acts_as_taggable_on :labels acts_as_taggable_on :labels
scope :cared, ->(user) { where(assignee_id: user) } scope :cared, ->(user) { where(assignee_id: user) }
......
...@@ -19,8 +19,6 @@ class Key < ActiveRecord::Base ...@@ -19,8 +19,6 @@ class Key < ActiveRecord::Base
belongs_to :user belongs_to :user
attr_accessible :key, :title
before_validation :strip_white_space, :generate_fingerpint before_validation :strip_white_space, :generate_fingerpint
validates :title, presence: true, length: { within: 0..255 } validates :title, presence: true, length: { within: 0..255 }
......
...@@ -36,10 +36,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -36,10 +36,6 @@ class MergeRequest < ActiveRecord::Base
delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
attr_accessible :title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id,
:state_event, :description, :label_list
attr_accessor :should_remove_source_branch attr_accessor :should_remove_source_branch
# When this attribute is true some MR validation is ignored # When this attribute is true some MR validation is ignored
...@@ -62,11 +58,11 @@ class MergeRequest < ActiveRecord::Base ...@@ -62,11 +58,11 @@ class MergeRequest < ActiveRecord::Base
transition closed: :reopened transition closed: :reopened
end end
event :lock do event :lock_mr do
transition [:reopened, :opened] => :locked transition [:reopened, :opened] => :locked
end end
event :unlock do event :unlock_mr do
transition locked: :reopened transition locked: :reopened
end end
...@@ -297,6 +293,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -297,6 +293,8 @@ class MergeRequest < ActiveRecord::Base
message << title.to_s message << title.to_s
message << "\n\n" message << "\n\n"
message << description.to_s message << description.to_s
message << "\n\n"
message << "See merge request !#{iid}"
message message
end end
......
...@@ -22,8 +22,6 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -22,8 +22,6 @@ class MergeRequestDiff < ActiveRecord::Base
belongs_to :merge_request belongs_to :merge_request
attr_accessible :state, :st_commits, :st_diffs
delegate :target_branch, :source_branch, to: :merge_request, prefix: nil delegate :target_branch, :source_branch, to: :merge_request, prefix: nil
state_machine :state, initial: :empty do state_machine :state, initial: :empty do
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
class Milestone < ActiveRecord::Base class Milestone < ActiveRecord::Base
include InternalId include InternalId
attr_accessible :title, :description, :due_date, :state_event
belongs_to :project belongs_to :project
has_many :issues has_many :issues
has_many :merge_requests has_many :merge_requests
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
class Namespace < ActiveRecord::Base class Namespace < ActiveRecord::Base
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
attr_accessible :name, :description, :path
has_many :projects, dependent: :destroy has_many :projects, dependent: :destroy
belongs_to :owner, class_name: "User" belongs_to :owner, class_name: "User"
...@@ -25,12 +23,12 @@ class Namespace < ActiveRecord::Base ...@@ -25,12 +23,12 @@ class Namespace < ActiveRecord::Base
validates :name, presence: true, uniqueness: true, validates :name, presence: true, uniqueness: true,
length: { within: 0..255 }, length: { within: 0..255 },
format: { with: Gitlab::Regex.name_regex, format: { with: Gitlab::Regex.name_regex,
message: "only letters, digits, spaces & '_' '-' '.' allowed." } message: Gitlab::Regex.name_regex_message }
validates :description, length: { within: 0..255 } validates :description, length: { within: 0..255 }
validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 }, validates :path, uniqueness: { case_sensitive: false }, presence: true, length: { within: 1..255 },
exclusion: { in: Gitlab::Blacklist.path }, 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: Gitlab::Regex.path_regex_message }
delegate :name, to: :owner, allow_nil: true, prefix: true delegate :name, to: :owner, allow_nil: true, prefix: true
......
...@@ -25,8 +25,6 @@ class Note < ActiveRecord::Base ...@@ -25,8 +25,6 @@ class Note < ActiveRecord::Base
default_value_for :system, false default_value_for :system, false
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id
attr_mentionable :note attr_mentionable :note
belongs_to :project belongs_to :project
...@@ -63,13 +61,13 @@ class Note < ActiveRecord::Base ...@@ -63,13 +61,13 @@ class Note < ActiveRecord::Base
def create_status_change_note(noteable, project, author, status, source) def create_status_change_note(noteable, project, author, status, source)
body = "_Status changed to #{status}#{' by ' + source.gfm_reference if source}_" body = "_Status changed to #{status}#{' by ' + source.gfm_reference if source}_"
create({ create(
noteable: noteable, noteable: noteable,
project: project, project: project,
author: author, author: author,
note: body, note: body,
system: true system: true
}, without_protection: true) )
end end
# +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note. # +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note.
...@@ -88,7 +86,7 @@ class Note < ActiveRecord::Base ...@@ -88,7 +86,7 @@ class Note < ActiveRecord::Base
note_options.merge!(noteable: noteable) note_options.merge!(noteable: noteable)
end end
create(note_options, without_protection: true) create(note_options)
end end
def create_milestone_change_note(noteable, project, author, milestone) def create_milestone_change_note(noteable, project, author, milestone)
...@@ -98,13 +96,13 @@ class Note < ActiveRecord::Base ...@@ -98,13 +96,13 @@ class Note < ActiveRecord::Base
"_Milestone changed to #{milestone.title}_" "_Milestone changed to #{milestone.title}_"
end end
create({ create(
noteable: noteable, noteable: noteable,
project: project, project: project,
author: author, author: author,
note: body, note: body,
system: true system: true
}, without_protection: true) )
end end
def create_assignee_change_note(noteable, project, author, assignee) def create_assignee_change_note(noteable, project, author, assignee)
...@@ -116,7 +114,7 @@ class Note < ActiveRecord::Base ...@@ -116,7 +114,7 @@ class Note < ActiveRecord::Base
author: author, author: author,
note: body, note: body,
system: true system: true
}, without_protection: true) })
end end
def discussions_from_notes(notes) def discussions_from_notes(notes)
......
...@@ -27,24 +27,20 @@ ...@@ -27,24 +27,20 @@
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel include Gitlab::VisibilityLevel
include Gitlab::ConfigHelper
extend Gitlab::ConfigHelper
extend Enumerize extend Enumerize
default_value_for :archived, false default_value_for :archived, false
default_value_for :issues_enabled, true default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :merge_requests_enabled, true default_value_for :issues_enabled, gitlab_config_features.issues
default_value_for :wiki_enabled, true default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests
default_value_for :wiki_enabled, gitlab_config_features.wiki
default_value_for :wall_enabled, false default_value_for :wall_enabled, false
default_value_for :snippets_enabled, true default_value_for :snippets_enabled, gitlab_config_features.snippets
ActsAsTaggableOn.strict_case_match = true ActsAsTaggableOn.strict_case_match = true
attr_accessible :name, :path, :description, :issues_tracker, :label_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at,
:merge_requests_template, as: [:default, :admin]
attr_accessible :namespace_id, :creator_id, as: :admin
acts_as_taggable_on :labels, :issues_default_labels acts_as_taggable_on :labels, :issues_default_labels
attr_accessor :new_default_branch attr_accessor :new_default_branch
...@@ -101,13 +97,16 @@ class Project < ActiveRecord::Base ...@@ -101,13 +97,16 @@ class Project < ActiveRecord::Base
validates :description, length: { maximum: 2000 }, allow_blank: true validates :description, length: { maximum: 2000 }, allow_blank: true
validates :name, presence: true, length: { within: 0..255 }, validates :name, presence: true, length: { within: 0..255 },
format: { with: Gitlab::Regex.project_name_regex, format: { with: Gitlab::Regex.project_name_regex,
message: "only letters, digits, spaces & '_' '-' '.' allowed. Letter or digit should be first" } message: Gitlab::Regex.project_regex_message }
validates :path, presence: true, length: { within: 0..255 }, validates :path, presence: true, length: { within: 0..255 },
exclusion: { in: Gitlab::Blacklist.path }, exclusion: { in: Gitlab::Blacklist.path },
format: { with: Gitlab::Regex.path_regex, format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter or digit should be first" } message: Gitlab::Regex.path_regex_message }
validates :issues_enabled, :merge_requests_enabled, validates :issues_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] } :wiki_enabled, inclusion: { in: [true, false] }
validates :visibility_level,
exclusion: { in: gitlab_config.restricted_visibility_levels },
if: -> { gitlab_config.restricted_visibility_levels.any? }
validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true validates :issues_tracker_id, length: { maximum: 255 }, allow_blank: true
validates :namespace, presence: true validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :name, scope: :namespace_id
...@@ -251,7 +250,7 @@ class Project < ActiveRecord::Base ...@@ -251,7 +250,7 @@ class Project < ActiveRecord::Base
end end
def check_limit def check_limit
unless creator.can_create_project? unless creator.can_create_project? or namespace.kind == 'group'
errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") errors[:limit_reached] << ("Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it")
end end
rescue rescue
...@@ -263,7 +262,7 @@ class Project < ActiveRecord::Base ...@@ -263,7 +262,7 @@ class Project < ActiveRecord::Base
end end
def web_url def web_url
[Gitlab.config.gitlab.url, path_with_namespace].join("/") [gitlab_config.url, path_with_namespace].join("/")
end end
def web_url_without_protocol def web_url_without_protocol
...@@ -403,7 +402,11 @@ class Project < ActiveRecord::Base ...@@ -403,7 +402,11 @@ class Project < ActiveRecord::Base
services.each do |service| services.each do |service|
# Call service hook only if it is active # Call service hook only if it is active
begin
service.execute(data) if service.active service.execute(data) if service.active
rescue => e
logger.error(e)
end
end end
end end
...@@ -488,7 +491,7 @@ class Project < ActiveRecord::Base ...@@ -488,7 +491,7 @@ class Project < ActiveRecord::Base
end end
def http_url_to_repo def http_url_to_repo
[Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') [gitlab_config.url, "/", path_with_namespace, ".git"].join('')
end end
# Check if current branch name is marked as protected in the system # Check if current branch name is marked as protected in the system
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
class ProjectHook < WebHook class ProjectHook < WebHook
belongs_to :project belongs_to :project
attr_accessible :push_events, :issues_events, :merge_requests_events, :tag_push_events
scope :push_hooks, -> { where(push_events: true) } scope :push_hooks, -> { where(push_events: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true) } scope :tag_push_hooks, -> { where(tag_push_events: true) }
scope :issue_hooks, -> { where(issues_events: true) } scope :issue_hooks, -> { where(issues_events: true) }
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class AssemblaService < Service class AssemblaService < Service
attr_accessible :subdomain
include HTTParty include HTTParty
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class CampfireService < Service class CampfireService < Service
attr_accessible :subdomain, :room
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
def title def title
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class EmailsOnPushService < Service class EmailsOnPushService < Service
attr_accessible :recipients
validates :recipients, presence: true, if: :activated? validates :recipients, presence: true, if: :activated?
def title def title
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class GitlabCiService < CiService class GitlabCiService < CiService
attr_accessible :project_url
validates :project_url, presence: true, if: :activated? validates :project_url, presence: true, if: :activated?
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class HipchatService < Service class HipchatService < Service
attr_accessible :room
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
def title def title
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
# #
class JenkinsService < CiService class JenkinsService < CiService
attr_accessible :project_url
validates :project_url, presence: true, if: :activated? validates :project_url, presence: true, if: :activated?
delegate :execute, to: :service_hook, prefix: nil delegate :execute, to: :service_hook, prefix: nil
......
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
# api_version :string(255) # api_version :string(255)
class JiraService < Service class JiraService < Service
include HTTParty include HTTParty
attr_accessible :project_url, :username, :password, :api_version
validates :username, :password, presence: true, if: :activated? validates :username, :password, presence: true, if: :activated?
before_validation :set_api_version before_validation :set_api_version
......
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
# #
class SlackService < Service class SlackService < Service
attr_accessible :room
attr_accessible :subdomain
validates :room, presence: true, if: :activated? validates :room, presence: true, if: :activated?
validates :subdomain, presence: true, if: :activated? validates :subdomain, presence: true, if: :activated?
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
class ProtectedBranch < ActiveRecord::Base class ProtectedBranch < ActiveRecord::Base
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
attr_accessible :name
belongs_to :project belongs_to :project
validates :name, presence: true validates :name, presence: true
validates :project, presence: true validates :project, presence: true
......
...@@ -242,4 +242,25 @@ class Repository ...@@ -242,4 +242,25 @@ class Repository
branches branches
end end
end end
def contributors
log = graph_log.group_by { |i| i[:author_email] }
log.map do |email, contributions|
contributor = Gitlab::Contributor.new
contributor.email = email
contributions.each do |contribution|
if contributor.name.blank?
contributor.name = contribution[:author_name]
end
contributor.commits += 1
contributor.additions += contribution[:additions] || 0
contributor.deletions += contribution[:deletions] || 0
end
contributor
end
end
end end
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
class Service < ActiveRecord::Base class Service < ActiveRecord::Base
default_value_for :active, false default_value_for :active, false
attr_accessible :title, :token, :type, :active, :api_key
belongs_to :project belongs_to :project
has_one :service_hook has_one :service_hook
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
class Snippet < ActiveRecord::Base class Snippet < ActiveRecord::Base
include Linguist::BlobHelper include Linguist::BlobHelper
attr_accessible :title, :content, :file_name, :expires_at, :private
default_value_for :private, true default_value_for :private, true
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
......
...@@ -50,31 +50,25 @@ require 'carrierwave/orm/activerecord' ...@@ -50,31 +50,25 @@ require 'carrierwave/orm/activerecord'
require 'file_size_validator' require 'file_size_validator'
class User < ActiveRecord::Base class User < ActiveRecord::Base
include Gitlab::ConfigHelper
extend Gitlab::ConfigHelper
include TokenAuthenticatable
default_value_for :admin, false default_value_for :admin, false
default_value_for :can_create_group, true default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false default_value_for :hide_no_ssh_key, false
default_value_for :projects_limit, gitlab_config.default_projects_limit
default_value_for :theme_id, gitlab_config.default_theme
devise :database_authenticatable, :token_authenticatable, :lockable, :async, devise :database_authenticatable, :lockable, :async,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key,
as: [:default, :admin]
attr_accessible :projects_limit, :can_create_group,
as: :admin
attr_accessor :force_random_password attr_accessor :force_random_password
# Virtual attribute for authenticating by either username or email # Virtual attribute for authenticating by either username or email
attr_accessor :login attr_accessor :login
# Add login to attr_accessible
attr_accessible :login
# #
# Relations # Relations
# #
...@@ -120,7 +114,7 @@ class User < ActiveRecord::Base ...@@ -120,7 +114,7 @@ class User < ActiveRecord::Base
validates :username, presence: true, uniqueness: { case_sensitive: false }, validates :username, presence: true, uniqueness: { case_sensitive: false },
exclusion: { in: Gitlab::Blacklist.path }, 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: Gitlab::Regex.username_regex_message }
validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :namespace_uniq, if: ->(user) { user.username_changed? }
...@@ -223,20 +217,8 @@ class User < ActiveRecord::Base ...@@ -223,20 +217,8 @@ class User < ActiveRecord::Base
where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first
end end
def build_user(attrs = {}, options= {}) def build_user(attrs = {})
if options[:as] == :admin User.new(attrs)
User.new(defaults.merge(attrs.symbolize_keys), options)
else
User.new(attrs, options).with_defaults
end
end
def defaults
{
projects_limit: Gitlab.config.gitlab.default_projects_limit,
can_create_group: Gitlab.config.gitlab.default_can_create_group,
theme_id: Gitlab.config.gitlab.default_theme
}
end end
end end
...@@ -315,7 +297,7 @@ class User < ActiveRecord::Base ...@@ -315,7 +297,7 @@ class User < ActiveRecord::Base
end end
def can_change_username? def can_change_username?
Gitlab.config.gitlab.username_changing_enabled gitlab_config.username_changing_enabled
end end
def can_create_project? def can_create_project?
...@@ -490,7 +472,7 @@ class User < ActiveRecord::Base ...@@ -490,7 +472,7 @@ class User < ActiveRecord::Base
def avatar_url(size = nil) def avatar_url(size = nil)
if avatar.present? if avatar.present?
URI::join(Gitlab.config.gitlab.url, avatar.url).to_s URI::join(gitlab_config.url, avatar.url).to_s
else else
GravatarService.new.execute(email, size) GravatarService.new.execute(email, size)
end end
......
...@@ -19,8 +19,6 @@ class UsersGroup < ActiveRecord::Base ...@@ -19,8 +19,6 @@ class UsersGroup < ActiveRecord::Base
Gitlab::Access.options_with_owner Gitlab::Access.options_with_owner
end end
attr_accessible :group_access, :user_id
belongs_to :user belongs_to :user
belongs_to :group belongs_to :group
......
...@@ -16,8 +16,6 @@ class UsersProject < ActiveRecord::Base ...@@ -16,8 +16,6 @@ class UsersProject < ActiveRecord::Base
include Notifiable include Notifiable
include Gitlab::Access include Gitlab::Access
attr_accessible :user, :user_id, :project_access
belongs_to :user belongs_to :user
belongs_to :project belongs_to :project
...@@ -126,7 +124,7 @@ class UsersProject < ActiveRecord::Base ...@@ -126,7 +124,7 @@ class UsersProject < ActiveRecord::Base
author_id: self.user.id author_id: self.user.id
) )
notification_service.new_team_member(self) notification_service.new_team_member(self) unless owner?
system_hook_service.execute_hooks_for(self, :create) system_hook_service.execute_hooks_for(self, :create)
end end
......
...@@ -22,8 +22,6 @@ class WebHook < ActiveRecord::Base ...@@ -22,8 +22,6 @@ class WebHook < ActiveRecord::Base
default_value_for :issues_events, false default_value_for :issues_events, false
default_value_for :merge_requests_events, false default_value_for :merge_requests_events, false
attr_accessible :url
# HTTParty timeout # HTTParty timeout
default_timeout 10 default_timeout 10
......
...@@ -25,7 +25,10 @@ module Files ...@@ -25,7 +25,10 @@ module Files
file_path = path file_path = path
unless file_name =~ Gitlab::Regex.path_regex unless file_name =~ Gitlab::Regex.path_regex
return error("Your changes could not be committed, because file name contains not allowed characters") return error(
'Your changes could not be committed, because the file name ' +
Gitlab::Regex.path_regex_message
)
end end
blob = repository.blob_at_branch(ref, file_path) blob = repository.blob_at_branch(ref, file_path)
......
...@@ -4,6 +4,7 @@ module Issues ...@@ -4,6 +4,7 @@ module Issues
if issue.reopen if issue.reopen
event_service.reopen_issue(issue, current_user) event_service.reopen_issue(issue, current_user)
create_note(issue) create_note(issue)
notification_service.reopen_issue(issue, current_user)
execute_hooks(issue, 'reopen') execute_hooks(issue, 'reopen')
end end
......
module Issues module Issues
class UpdateService < Issues::BaseService class UpdateService < Issues::BaseService
def execute(issue) def execute(issue)
state = params.delete('state_event') || params.delete(:state_event) state = params[:state_event]
case state case state
when 'reopen' when 'reopen'
...@@ -10,7 +10,7 @@ module Issues ...@@ -10,7 +10,7 @@ module Issues
Issues::CloseService.new(project, current_user, {}).execute(issue) Issues::CloseService.new(project, current_user, {}).execute(issue)
end end
if params.present? && issue.update_attributes(params) if params.present? && issue.update_attributes(params.except(:state_event))
issue.reset_events_cache issue.reset_events_cache
if issue.previous_changes.include?('milestone_id') if issue.previous_changes.include?('milestone_id')
......
...@@ -6,7 +6,7 @@ module MergeRequests ...@@ -6,7 +6,7 @@ module MergeRequests
# Called when you do merge via GitLab UI # Called when you do merge via GitLab UI
class AutoMergeService < BaseMergeService class AutoMergeService < BaseMergeService
def execute(merge_request, current_user, commit_message) def execute(merge_request, current_user, commit_message)
merge_request.lock merge_request.lock_mr
if Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message) if Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message)
merge_request.merge merge_request.merge
...@@ -17,11 +17,11 @@ module MergeRequests ...@@ -17,11 +17,11 @@ module MergeRequests
true true
else else
merge_request.unlock merge_request.unlock_mr
false false
end end
rescue rescue
merge_request.unlock if merge_request.locked? merge_request.unlock_mr if merge_request.locked?
merge_request.mark_as_unmergeable merge_request.mark_as_unmergeable
false false
end end
......
...@@ -3,6 +3,7 @@ module MergeRequests ...@@ -3,6 +3,7 @@ module MergeRequests
def execute(merge_request) def execute(merge_request)
if merge_request.reopen if merge_request.reopen
event_service.reopen_mr(merge_request, current_user) event_service.reopen_mr(merge_request, current_user)
notification_service.reopen_mr(merge_request, current_user)
create_note(merge_request) create_note(merge_request)
execute_hooks(merge_request) execute_hooks(merge_request)
merge_request.reload_code merge_request.reload_code
......
...@@ -7,10 +7,10 @@ module MergeRequests ...@@ -7,10 +7,10 @@ module MergeRequests
def execute(merge_request) def execute(merge_request)
# We dont allow change of source/target projects # We dont allow change of source/target projects
# after merge request was created # after merge request was created
params.delete(:source_project_id) params.except!(:source_project_id)
params.delete(:target_project_id) params.except!(:target_project_id)
state = params.delete('state_event') || params.delete(:state_event) state = params[:state_event]
case state case state
when 'reopen' when 'reopen'
...@@ -19,7 +19,7 @@ module MergeRequests ...@@ -19,7 +19,7 @@ module MergeRequests
MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request) MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request)
end end
if params.present? && merge_request.update_attributes(params) if params.present? && merge_request.update_attributes(params.except(:state_event))
merge_request.reset_events_cache merge_request.reset_events_cache
if merge_request.previous_changes.include?('milestone_id') if merge_request.previous_changes.include?('milestone_id')
......
module Milestones
class GroupService < Milestones::BaseService
def initialize(project_milestones)
@project_milestones = project_milestones.group_by(&:title)
end
def execute
build(@project_milestones)
end
def milestone(title)
if title
group_milestone = @project_milestones[title].group_by(&:title)
build(group_milestone).first
else
nil
end
end
private
def build(milestone)
milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) }
end
end
end
module Milestones module Milestones
class UpdateService < Milestones::BaseService class UpdateService < Milestones::BaseService
def execute(milestone) def execute(milestone)
state = params.delete('state_event') || params.delete(:state_event) state = params[:state_event]
case state case state
when 'activate' when 'activate'
...@@ -11,7 +11,7 @@ module Milestones ...@@ -11,7 +11,7 @@ module Milestones
end end
if params.present? if params.present?
milestone.update_attributes(params) milestone.update_attributes(params.except(:state_event))
end end
milestone milestone
......
...@@ -80,6 +80,10 @@ class NotificationService ...@@ -80,6 +80,10 @@ class NotificationService
close_resource_email(merge_request, merge_request.target_project, current_user, 'closed_merge_request_email') close_resource_email(merge_request, merge_request.target_project, current_user, 'closed_merge_request_email')
end end
def reopen_issue(issue, current_user)
reopen_resource_email(issue, issue.project, current_user, 'issue_status_changed_email', 'reopened')
end
# When we merge a merge request we should send next emails: # When we merge a merge request we should send next emails:
# #
# * merge_request author if their notification level is not Disabled # * merge_request author if their notification level is not Disabled
...@@ -89,12 +93,17 @@ class NotificationService ...@@ -89,12 +93,17 @@ class NotificationService
def merge_mr(merge_request, current_user) def merge_mr(merge_request, current_user)
recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project) recipients = reject_muted_users([merge_request.author, merge_request.assignee], merge_request.target_project)
recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq recipients = recipients.concat(project_watchers(merge_request.target_project)).uniq
recipients.delete(current_user)
recipients.each do |recipient| recipients.each do |recipient|
mailer.merged_merge_request_email(recipient.id, merge_request.id, current_user.id) mailer.merged_merge_request_email(recipient.id, merge_request.id, current_user.id)
end end
end end
def reopen_mr(merge_request, current_user)
reopen_resource_email(merge_request, merge_request.target_project, current_user, 'merge_request_status_email', 'reopened')
end
# Notify new user with email after creation # Notify new user with email after creation
def new_user(user) def new_user(user)
# Don't email omniauth created users # Don't email omniauth created users
...@@ -301,7 +310,9 @@ class NotificationService ...@@ -301,7 +310,9 @@ class NotificationService
end end
def reassign_resource_email(target, project, current_user, method) def reassign_resource_email(target, project, current_user, method)
recipients = User.where(id: [target.assignee_id, target.assignee_id_was]) assignee_id_was = previous_record(target, "assignee_id")
recipients = User.where(id: [target.assignee_id, assignee_id_was])
# Add watchers to email list # Add watchers to email list
recipients = recipients.concat(project_watchers(project)) recipients = recipients.concat(project_watchers(project))
...@@ -313,11 +324,29 @@ class NotificationService ...@@ -313,11 +324,29 @@ class NotificationService
recipients.delete(current_user) recipients.delete(current_user)
recipients.each do |recipient| recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, target.assignee_id_was, current_user.id) mailer.send(method, recipient.id, target.id, assignee_id_was, current_user.id)
end
end
def reopen_resource_email(target, project, current_user, method, status)
recipients = reject_muted_users([target.author, target.assignee], project)
recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(current_user)
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, status, current_user.id)
end end
end end
def mailer def mailer
Notify.delay Notify.delay
end end
def previous_record(object, attribute)
if object && attribute
if object.previous_changes.include?(attribute)
object.previous_changes[attribute].first
end
end
end
end end
...@@ -5,27 +5,13 @@ module Projects ...@@ -5,27 +5,13 @@ module Projects
end end
def execute def execute
# get namespace id @project = Project.new(params)
namespace_id = params.delete(:namespace_id)
# check that user is allowed to set specified visibility_level # Reset visibility levet if is not allowed to set it
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level]) unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
params.delete(:visibility_level) @project.visibility_level = default_features.visibility_level
end end
# Load default feature settings
default_features = Gitlab.config.gitlab.default_projects_features
default_opts = {
issues_enabled: default_features.issues,
wiki_enabled: default_features.wiki,
snippets_enabled: default_features.snippets,
merge_requests_enabled: default_features.merge_requests,
visibility_level: default_features.visibility_level
}.stringify_keys
@project = Project.new(default_opts.merge(params))
# Parametrize path for project # Parametrize path for project
# #
# Ex. # Ex.
...@@ -33,13 +19,14 @@ module Projects ...@@ -33,13 +19,14 @@ module Projects
# #
@project.path = @project.name.dup.parameterize unless @project.path.present? @project.path = @project.name.dup.parameterize unless @project.path.present?
# get namespace id
namespace_id = params[:namespace_id]
if namespace_id if namespace_id
# Find matching namespace and check if it allowed # Find matching namespace and check if it allowed
# for current user if namespace_id passed. # for current user if namespace_id passed.
if allowed_namespace?(current_user, namespace_id) unless allowed_namespace?(current_user, namespace_id)
@project.namespace_id = namespace_id @project.namespace_id = nil
else
deny_namespace deny_namespace
return @project return @project
end end
......
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.
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.
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