Commit 2bb2ade5 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into license

# Conflicts:
#	db/schema.rb
parents caa09e69 68ee3972
......@@ -37,6 +37,6 @@ public/assets/
public/uploads.*
public/uploads/
rails_best_practices_output.html
tags
/tags
tmp/
vendor/bundle/*
Please view this file on the master branch, on stable branches it's out of date.
v 7.11.0 (unreleased)
- Make Reply-To config apply to change e-mail confirmation and other Devise notifications (Stan Hu)
- Add application setting to restrict user signups to e-mail domains (Stan Hu)
- Don't allow a merge request to be merged when its title starts with "WIP".
- Add a page title to every page.
- Allow primary email to be set to an email that you've already added.
- Fix Error 500 when searching Wiki pages (Stan Hu)
- Get Gitorious importer to work again.
- Fix clone URL field and X11 Primary selection (Dmitry Medvinsky)
- Ignore invalid lines in .gitmodules
- Fix "Cannot move project" error message from popping up after a successful transfer (Stan Hu)
- Redirect to sign in page after signing out.
- Fix "Hello @username." references not working by no longer allowing usernames to end in period.
- Fix "Revspec not found" errors when viewing diffs in a forked project with submodules (Stan Hu)
-
- Fix broken file browsing with relative submodule in personal projects (Stan Hu)
- Fix DB error when trying to tag a repository (Stan Hu)
- Add "Reply quoting selected text" shortcut key (`r`)
- Fix bug causing `@whatever` inside an issue's first code block to be picked up as a user mention.
- Fix bug causing `@whatever` inside an inline code snippet (backtick-style) to be picked up as a user mention.
- Added GitLab Event header for project hooks
-
- Show Atom feed buttons everywhere where applicable.
- Add project activity atom feed.
- Don't crash when an MR from a fork has a cross-reference comment from the target project on of its commits.
- Don't crash when an MR from a fork has a cross-reference comment from the target project on one of its commits.
- Include commit comments in MR from a forked project.
-
- Fix adding new group members from admin area
- Group milestones by title in the dashboard and all other issue views.
- Query issues, merge requests and milestones with their IID through API (Julien Bianchi)
- Add default project and snippet visibility settings to the admin web UI.
- Show incompatible projects in Google Code import status (Stan Hu)
- Fix bug where commit data would not appear in some subdirectories (Stan Hu)
- Unescape branch names in compare commit (Stan Hu)
-
- Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu)
- Move snippets UI to fluid layout
- Improve UI for sidebar. Increase separation between navigation and content
- Improve new project command options (Ben Bodenmiller)
- Add common method to force UTF-8 and use it to properly handle non-ascii OAuth user properties (Onur Küçük)
- Prevent sending empty messages to HipChat (Chulki Lee)
- Improve UI for mobile phones on dashboard and project pages
- Add room notification and message color option for HipChat
- Allow to use non-ASCII letters and dashes in project and namespace name. (Jakub Jirutka)
- Add footnotes support to Markdown (Guillaume Delbergue)
- Add current_sign_in_at to UserFull REST api.
v 7.10.0
- Ignore submodules that are defined in .gitmodules but are checked in as directories.
......@@ -111,7 +129,6 @@ v 7.9.0 (unreleased)
- Fixed link paths for HTTP and SSH on the admin project view (Jeremy Maziarz)
- Fix and improve help rendering (Sullivan Sénéchal)
- Fix final line in EmailsOnPush email diff being rendered as error.
- Authometic setup GitLab CI project for forks if origin project has GitLab CI enabled
- Prevent duplicate Buildkite service creation.
- Fix git over ssh errors 'fatal: protocol error: bad line length character'
- Automatically setup GitLab CI project for forks if origin project has GitLab CI enabled
......
......@@ -211,6 +211,7 @@ group :development do
gem "letter_opener"
gem 'quiet_assets', '~> 1.0.1'
gem 'rack-mini-profiler', require: false
gem 'rerun', '~> 0.10.0'
# Better errors handler
gem 'better_errors'
......
......@@ -47,7 +47,7 @@ GEM
astrolabe (1.3.0)
parser (>= 2.2.0.pre.3, < 3.0)
attr_required (1.0.0)
autoprefixer-rails (5.1.6)
autoprefixer-rails (5.1.11)
execjs
json
awesome_print (1.2.0)
......@@ -60,7 +60,7 @@ GEM
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootstrap-sass (3.3.3)
bootstrap-sass (3.3.4.1)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.2.19)
brakeman (3.0.1)
......@@ -154,7 +154,7 @@ GEM
escape_utils (0.2.4)
eventmachine (1.0.4)
excon (0.32.1)
execjs (2.0.2)
execjs (2.5.2)
expression_parser (0.9.0)
factory_girl (4.3.0)
activesupport (>= 3.0.0)
......@@ -167,7 +167,7 @@ GEM
faraday (>= 0.7.4, < 0.9)
fastercsv (1.5.5)
ffaker (1.22.1)
ffi (1.9.3)
ffi (1.9.8)
fog (1.21.0)
fog-brightbox
fog-core (~> 1.21, >= 1.21.1)
......@@ -324,8 +324,8 @@ GEM
addressable (~> 2.3)
letter_opener (1.1.2)
launchy (~> 2.2)
listen (2.3.1)
celluloid (>= 0.15.2)
listen (2.10.0)
celluloid (~> 0.16.0)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.4)
......@@ -457,8 +457,8 @@ GEM
raindrops (0.13.0)
rake (10.4.2)
raphael-rails (2.1.2)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
rb-fsevent (0.9.4)
rb-inotify (0.9.5)
ffi (>= 0.5.0)
rdoc (3.12.2)
json (~> 1.4)
......@@ -483,6 +483,8 @@ GEM
redis-store (1.1.4)
redis (>= 2.2)
request_store (1.0.5)
rerun (0.10.0)
listen (~> 2.7, >= 2.7.3)
rest-client (1.6.7)
mime-types (>= 1.16)
rinku (1.7.3)
......@@ -766,6 +768,7 @@ DEPENDENCIES
redcarpet (~> 3.2.3)
redis-rails
request_store
rerun (~> 0.10.0)
rspec-rails (= 2.99)
rubocop (= 0.28.0)
rugments
......
......@@ -8,7 +8,6 @@ class Dispatcher
initPageScripts: ->
page = $('body').attr('data-page')
project_id = $('body').attr('data-project-id')
unless page
return false
......
......@@ -137,6 +137,12 @@
color: #666;
}
.nav-pills > .active > a > span > .badge {
background-color: #fff;
color: $gl-primary;
}
/**
* fix to keep tooltips position in top navigation bar
*
......
......@@ -342,17 +342,8 @@ table {
}
.search_box {
position: relative;
padding: 30px;
@extend .well;
text-align: center;
background-color: #F9F9F9;
border: 1px solid #DDDDDD;
border-radius: 0px;
}
.search_glyph {
color: #555;
font-size: 42px;
}
.task-status {
......
......@@ -10,7 +10,10 @@ header {
border: none;
width: 100%;
.navbar-inner {
.container {
width: 100% !important;
padding: 0;
background: #FFF;
border-bottom: 1px solid #DDD;
filter: none;
......@@ -123,11 +126,6 @@ header {
}
}
.container {
width: 100% !important;
padding: 0px;
}
/**
*
* Logo holder
......
......@@ -56,7 +56,7 @@
}
}
.navbar-inner .title {
.container .title {
margin-left: 6px !important;
max-width: 70% !important;
}
......
......@@ -35,7 +35,12 @@ pre {
/* Link to current header. */
h1, h2, h3, h4, h5, h6 {
position: relative;
&:hover > :last-child {
a.anchor {
display: none;
}
&:hover > a.anchor {
$size: 16px;
position: absolute;
right: 100%;
......
......@@ -19,7 +19,7 @@
&.affix {
position: fixed;
top: 70px;
width: 220px;
margin-right: 35px;
}
}
}
......
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
header {
&.navbar-gitlab {
.navbar-inner {
.app_logo {
background-color: $color-darker;
.app_logo {
background-color: $color-darker;
a {
color: $color-light;
}
a {
color: $color-light;
}
&:hover {
background-color: $color-dark;
a {
color: #FFF;
}
&:hover {
background-color: $color-dark;
a {
color: #FFF;
}
}
}
......
......@@ -2,8 +2,8 @@
#
# Automatically sets the layout and ensures an administrator is logged in
class Admin::ApplicationController < ApplicationController
layout 'admin'
before_action :authenticate_admin!
layout 'admin'
def authenticate_admin!
return render_404 unless current_user.is_admin?
......
......@@ -42,7 +42,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:max_attachment_size,
:default_project_visibility,
:default_snippet_visibility,
restricted_visibility_levels: []
:restricted_signup_domains_raw,
restricted_visibility_levels: [],
)
end
end
......@@ -33,7 +33,7 @@ class Admin::HooksController < Admin::ApplicationController
owner_name: "Someone",
owner_email: "example@gitlabhq.com"
}
@hook.execute(data, 'system_hooks')
@hook.execute(data)
redirect_to :back
end
......
......@@ -102,8 +102,7 @@ class Admin::UsersController < Admin::ApplicationController
email = user.emails.find(params[:email_id])
email.destroy
user.set_notification_email
user.save if user.notification_email_changed?
user.update_secondary_emails!
respond_to do |format|
format.html { redirect_to :back, notice: "Successfully removed email." }
......
......@@ -3,6 +3,7 @@ require 'gon'
class ApplicationController < ActionController::Base
include Gitlab::CurrentSettings
include GitlabRoutingHelper
include PageLayoutHelper
PER_PAGE = 20
......@@ -182,18 +183,6 @@ class ApplicationController < ActionController::Base
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
end
def default_url_options
if !Rails.env.test?
port = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port?
{ host: Gitlab.config.gitlab.host,
protocol: Gitlab.config.gitlab.protocol,
port: port,
script_name: Gitlab.config.gitlab.relative_url_root }
else
super
end
end
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
......@@ -304,40 +293,15 @@ class ApplicationController < ActionController::Base
@filter_params
end
def set_filter_values(collection)
assignee_id = @filter_params[:assignee_id]
author_id = @filter_params[:author_id]
milestone_id = @filter_params[:milestone_id]
@sort = @filter_params[:sort]
@assignees = User.where(id: collection.pluck(:assignee_id))
@authors = User.where(id: collection.pluck(:author_id))
@milestones = Milestone.where(id: collection.pluck(:milestone_id))
if assignee_id.present? && !assignee_id.to_i.zero?
@assignee = @assignees.find_by(id: assignee_id)
end
if author_id.present? && !author_id.to_i.zero?
@author = @authors.find_by(id: author_id)
end
if milestone_id.present? && !milestone_id.to_i.zero?
@milestone = @milestones.find_by(id: milestone_id)
end
end
def get_issues_collection
set_filters_params
issues = IssuesFinder.new.execute(current_user, @filter_params)
set_filter_values(issues)
issues
end
def get_merge_requests_collection
set_filters_params
merge_requests = MergeRequestsFinder.new.execute(current_user, @filter_params)
set_filter_values(merge_requests)
merge_requests
end
......
class Dashboard::ApplicationController < ApplicationController
layout 'dashboard'
end
class Dashboard::GroupsController < ApplicationController
class Dashboard::GroupsController < Dashboard::ApplicationController
def index
@group_members = current_user.group_members.page(params[:page]).per(PER_PAGE)
end
......
class Dashboard::MilestonesController < ApplicationController
class Dashboard::MilestonesController < Dashboard::ApplicationController
before_action :load_projects
def index
......
class Dashboard::ProjectsController < ApplicationController
class Dashboard::ProjectsController < Dashboard::ApplicationController
before_action :event_filter
def starred
......
class DashboardController < ApplicationController
respond_to :html
class DashboardController < Dashboard::ApplicationController
before_action :load_projects, except: [:projects]
before_action :event_filter, only: :show
respond_to :html
def show
@projects = @projects.includes(:namespace)
......
class Explore::ApplicationController < ApplicationController
layout 'explore'
end
class Explore::GroupsController < ApplicationController
class Explore::GroupsController < Explore::ApplicationController
skip_before_action :authenticate_user!,
:reject_blocked, :set_current_user_for_observers
layout "explore"
def index
@groups = GroupsFinder.new.execute(current_user)
@groups = @groups.search(params[:search]) if params[:search].present?
......
class Explore::ProjectsController < ApplicationController
class Explore::ProjectsController < Explore::ApplicationController
skip_before_action :authenticate_user!,
:reject_blocked
layout 'explore'
def index
@projects = ProjectsFinder.new.execute(current_user)
@tags = @projects.tags_on(:tags)
......
class Groups::ApplicationController < ApplicationController
layout 'group'
private
......@@ -21,12 +22,4 @@ class Groups::ApplicationController < ApplicationController
def group
@group ||= Group.find_by(path: params[:group_id])
end
def determine_layout
if current_user
'group'
else
'public_group'
end
end
end
class Groups::AvatarsController < ApplicationController
layout "profile"
def destroy
@group = Group.find_by(path: params[:group_id])
@group.remove_avatar!
......
......@@ -6,8 +6,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
before_action :authorize_read_group!
before_action :authorize_admin_group!, except: [:index, :leave]
layout :determine_layout
def index
@project = @group.projects.find(params[:project_id]) if params[:project_id]
@members = @group.group_members
......
class Groups::MilestonesController < ApplicationController
layout 'group'
class Groups::MilestonesController < Groups::ApplicationController
before_action :authorize_group_milestone!, only: :update
def index
......
......@@ -11,7 +11,6 @@ class GroupsController < Groups::ApplicationController
# Load group projects
before_action :load_projects, except: [:new, :create, :projects, :edit, :update]
before_action :event_filter, only: :show
before_action :set_title, only: [:new, :create]
layout :determine_layout
......@@ -121,17 +120,11 @@ class GroupsController < Groups::ApplicationController
end
end
def set_title
@title = 'New Group'
end
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'navless'
elsif current_user
'group'
'application'
else
'public_group'
'group'
end
end
......
class HelpController < ApplicationController
layout 'help'
def index
end
def show
category = clean_path_info(path_params[:category])
file = path_params[:file]
@category = clean_path_info(path_params[:category])
@file = path_params[:file]
respond_to do |format|
format.any(:markdown, :md, :html) do
path = Rails.root.join('doc', category, "#{file}.md")
path = Rails.root.join('doc', @category, "#{@file}.md")
if File.exist?(path)
@markdown = File.read(path)
......@@ -22,7 +24,7 @@ class HelpController < ApplicationController
# Allow access to images in the doc folder
format.any(:png, :gif, :jpeg) do
path = Rails.root.join('doc', category, "#{file}.#{params[:format]}")
path = Rails.root.join('doc', @category, "#{@file}.#{params[:format]}")
if File.exist?(path)
send_file(path, disposition: 'inline')
......
......@@ -72,6 +72,7 @@ class Import::GoogleCodeController < Import::BaseController
end
@repos = client.repos
@incompatible_repos = client.incompatible_repos
@already_added_projects = current_user.created_projects.where(import_type: "google_code")
already_added_projects_names = @already_added_projects.pluck(:import_source)
......
......@@ -4,8 +4,6 @@ class InvitesController < ApplicationController
respond_to :html
layout 'navless'
def show
end
......
class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
include PageLayoutHelper
before_action :authenticate_user!
layout "profile"
layout 'profile'
def index
head :forbidden and return
......
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_action :authenticate_resource_owner!
layout "profile"
layout 'profile'
def new
if pre_auth.authorizable?
......
class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
layout "profile"
include PageLayoutHelper
layout 'profile'
def destroy
Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner)
......
class Profiles::AccountsController < ApplicationController
layout "profile"
class Profiles::AccountsController < Profiles::ApplicationController
def show
@user = current_user
end
......
class Profiles::ApplicationController < ApplicationController
layout 'profile'
end
class Profiles::AvatarsController < ApplicationController
layout "profile"
class Profiles::AvatarsController < Profiles::ApplicationController
def destroy
@user = current_user
@user.remove_avatar!
......
class Profiles::EmailsController < ApplicationController
layout "profile"
class Profiles::EmailsController < Profiles::ApplicationController
def index
@primary = current_user.email
@public_email = current_user.public_email
@emails = current_user.emails
end
def create
@email = current_user.emails.new(email_params)
flash[:alert] = @email.errors.full_messages.first unless @email.save
if @email.save
NotificationService.new.new_email(@email)
else
flash[:alert] = @email.errors.full_messages.first
end
redirect_to profile_emails_url
end
......@@ -19,9 +20,7 @@ class Profiles::EmailsController < ApplicationController
@email = current_user.emails.find(params[:id])
@email.destroy
current_user.set_notification_email
current_user.set_public_email
current_user.save if current_user.notification_email_changed? or current_user.public_email_changed?
current_user.update_secondary_emails!
respond_to do |format|
format.html { redirect_to profile_emails_url }
......
class Profiles::KeysController < ApplicationController
layout "profile"
class Profiles::KeysController < Profiles::ApplicationController
skip_before_action :authenticate_user!, only: [:get_keys]
def index
......
class Profiles::NotificationsController < ApplicationController
layout 'profile'
class Profiles::NotificationsController < Profiles::ApplicationController
def show
@user = current_user
@notification = current_user.notification
......
class Profiles::PasswordsController < ApplicationController
layout :determine_layout
class Profiles::PasswordsController < Profiles::ApplicationController
skip_before_action :check_password_expiration, only: [:new, :create]
before_action :set_user
before_action :set_title
before_action :authorize_change_password!
layout :determine_layout
def new
end
......@@ -66,13 +65,9 @@ class Profiles::PasswordsController < ApplicationController
@user = current_user
end
def set_title
@title = "New password"
end
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'navless'
'application'
else
'profile'
end
......
class ProfilesController < ApplicationController
class ProfilesController < Profiles::ApplicationController
include ActionView::Helpers::SanitizeHelper
before_action :user
before_action :authorize_change_username!, only: :update_username
skip_before_action :require_email, only: [:show, :update]
layout 'profile'
def show
end
......
class Projects::ApplicationController < ApplicationController
before_action :project
before_action :repository
layout :determine_layout
layout 'project'
def authenticate_user!
# Restrict access to Projects area only
......@@ -17,14 +17,6 @@ class Projects::ApplicationController < ApplicationController
super
end
def determine_layout
if current_user
'projects'
else
'public_projects'
end
end
def require_branch_head
unless @repository.branch_names.include?(@ref)
redirect_to(
......
class Projects::AvatarsController < Projects::ApplicationController
layout 'project'
before_action :project
def show
......
require 'addressable/uri'
class Projects::CompareController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
......@@ -7,8 +9,8 @@ class Projects::CompareController < Projects::ApplicationController
end
def show
base_ref = params[:from]
head_ref = params[:to]
base_ref = Addressable::URI.unescape(params[:from])
head_ref = Addressable::URI.unescape(params[:to])
compare_result = CompareService.new.execute(
current_user,
......
......@@ -18,7 +18,6 @@ class Projects::ForksController < Projects::ApplicationController
notice: 'Project was successfully forked.'
)
else
@title = 'Fork project'
render :error
end
end
......
......@@ -124,13 +124,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request.check_if_can_be_merged
end
render json: { merge_status: @merge_request.merge_status_name }
render json: { merge_status: @merge_request.automerge_status }
end
def automerge
return access_denied! unless allowed_to_merge?
if @merge_request.open? && @merge_request.can_be_merged?
if @merge_request.automergeable?
AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params)
@status = true
else
......
class Projects::ServicesController < Projects::ApplicationController
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :subdomain,
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain,
:room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key, :server, :teamcity_url, :build_type,
......
class Projects::UploadsController < Projects::ApplicationController
layout 'project'
skip_before_action :authenticate_user!, :reject_blocked!, :project,
:repository, if: -> { action_name == 'show' && image? }
......
......@@ -6,17 +6,16 @@ class ProjectsController < ApplicationController
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
before_action :set_title, only: [:new, :create]
before_action :event_filter, only: :show
layout 'navless', only: [:new, :create, :fork]
layout :determine_layout
def new
@project = Project.new
end
def edit
render 'edit', layout: 'project_settings'
render 'edit'
end
def create
......@@ -46,7 +45,7 @@ class ProjectsController < ApplicationController
end
format.js
else
format.html { render 'edit', layout: 'project_settings' }
format.html { render 'edit' }
format.js
end
end
......@@ -72,13 +71,13 @@ class ProjectsController < ApplicationController
format.html do
if @project.repository_exists?
if @project.empty_repo?
render 'projects/empty', layout: user_layout
render 'projects/empty'
else
@last_push = current_user.recent_push(@project.id) if current_user
render :show, layout: user_layout
render :show
end
else
render 'projects/no_repo', layout: user_layout
render 'projects/no_repo'
end
end
......@@ -160,12 +159,14 @@ class ProjectsController < ApplicationController
private
def set_title
@title = 'New Project'
end
def user_layout
current_user ? 'projects' : 'public_projects'
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'application'
elsif [:edit, :update].include?(action_name.to_sym)
'project_settings'
else
'project'
end
end
def load_events
......
class SearchController < ApplicationController
include SearchHelper
layout 'search'
def show
return if params[:search].nil? || params[:search].blank?
@search_term = params[:search]
if params[:project_id].present?
@project = Project.find_by(id: params[:project_id])
@project = nil unless can?(current_user, :download_code, @project)
end
if params[:group_id].present?
@group = Group.find_by(id: params[:group_id])
@group = Group.find_by(id: params[:group_id])
@group = nil unless can?(current_user, :read_group, @group)
end
@scope = params[:scope]
@show_snippets = params[:snippets].eql? 'true'
@search_results =
@search_results =
if @project
unless %w(blobs notes issues merge_requests wiki_blobs).
include?(@scope)
......@@ -37,6 +41,7 @@ class SearchController < ApplicationController
end
Search::GlobalService.new(current_user, params).execute
end
@objects = @search_results.objects(@scope, params[:page])
end
......
......@@ -7,14 +7,11 @@ class SnippetsController < ApplicationController
# Allow destroy snippet
before_action :authorize_admin_snippet!, only: [:destroy]
before_action :set_title
skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw]
layout 'snippets'
respond_to :html
layout :determine_layout
def index
if params[:username].present?
@user = User.find_by(username: params[:username])
......@@ -98,16 +95,7 @@ class SnippetsController < ApplicationController
return render_404 unless can?(current_user, :admin_personal_snippet, @snippet)
end
def set_title
@title = 'Snippets'
@title_url = snippets_path
end
def snippet_params
params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level)
end
def determine_layout
current_user ? 'snippets' : 'public_users'
end
end
......@@ -2,7 +2,6 @@ class UnsubscribesController < ApplicationController
skip_before_action :authenticate_user!,
:reject_blocked, :set_current_user_for_observers,
:add_abilities
layout 'public_users'
def show
@user = get_user
......
class UsersController < ApplicationController
skip_before_action :authenticate_user!
before_action :set_user
layout :determine_layout
def show
@contributed_projects = contributed_projects.joined(@user).
......@@ -13,9 +12,6 @@ class UsersController < ApplicationController
# Collect only groups common for both users
@groups = @user.groups & GroupsFinder.new.execute(current_user)
@title = @user.name
@title_url = user_path(@user)
respond_to do |format|
format.html
......@@ -51,14 +47,6 @@ class UsersController < ApplicationController
render 'calendar_activities', layout: false
end
def determine_layout
if current_user
'navless'
else
'public_users'
end
end
private
def set_user
......
......@@ -113,8 +113,9 @@ class IssuableFinder
end
def by_milestone(items)
if params[:milestone_id].present?
items = items.where(milestone_id: (params[:milestone_id] == NONE ? nil : params[:milestone_id]))
if params[:milestone_title].present?
milestone_ids = (params[:milestone_title] == NONE ? nil : Milestone.where(title: params[:milestone_title]).pluck(:id))
items = items.where(milestone_id: milestone_ids)
end
items
......
......@@ -140,8 +140,8 @@ module DiffHelper
end
end
def submodule_link(blob, ref)
tree, commit = submodule_links(blob, ref)
def submodule_link(blob, ref, repository = @repository)
tree, commit = submodule_links(blob, ref, repository)
commit_id = if commit.nil?
blob.id[0..10]
else
......
......@@ -34,10 +34,8 @@ module GitlabMarkdownHelper
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, {
with_toc_data: true,
safe_links_only: true,
# Handled further down the line by HTML::Pipeline::SanitizationFilter
escape_html: false
# Handled further down the line by Gitlab::Markdown::SanitizationFilter
escape_html: false
}.merge(options))
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
......@@ -45,11 +43,11 @@ module GitlabMarkdownHelper
no_intra_emphasis: true,
tables: true,
fenced_code_blocks: true,
autolink: true,
strikethrough: true,
lax_spacing: true,
space_after_headers: true,
superscript: true
superscript: true,
footnotes: true
)
end
......
......@@ -19,24 +19,6 @@ module GroupsHelper
end
end
def group_head_title
title = @group.name
title = if current_action?(:issues)
"Issues - " + title
elsif current_action?(:merge_requests)
"Merge requests - " + title
elsif current_action?(:members)
"Members - " + title
elsif current_action?(:edit)
"Settings - " + title
else
title
end
title
end
def group_settings_page?
if current_controller?('groups')
current_action?('edit') || current_action?('projects')
......
......@@ -43,17 +43,6 @@ module IssuesHelper
end
end
def title_for_issue(issue_iid, project = @project)
return '' if project.nil?
if project.default_issues_tracker?
issue = project.issues.where(iid: issue_iid).first
return issue.title if issue
end
''
end
def issue_timestamp(issue)
# Shows the created at time and the updated at time if different
ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}"
......@@ -110,5 +99,5 @@ module IssuesHelper
end
# Required for Gitlab::Markdown::IssueReferenceFilter
module_function :url_for_issue, :title_for_issue
module_function :url_for_issue
end
......@@ -28,6 +28,7 @@ module MilestonesHelper
Milestone.where(project_id: @projects)
end.active
options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id])
grouped_milestones = Milestones::GroupService.new(milestones).execute
options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title])
end
end
module PageLayoutHelper
def page_title(*titles)
@page_title ||= []
@page_title.push(*titles.compact) if titles.any?
@page_title.join(" | ")
end
def header_title(title = nil, title_url = nil)
if title
@header_title = title
@header_title_url = title_url
else
@header_title_url ? link_to(@header_title, @header_title_url) : @header_title
end
end
def sidebar(name = nil)
if name
@sidebar = name
else
@sidebar
end
end
end
......@@ -192,46 +192,6 @@ module ProjectsHelper
'unknown'
end
def project_head_title
title = @project.name_with_namespace
title = if current_controller?(:tree)
"#{@project.path}\/#{@path} at #{@ref} - " + title
elsif current_controller?(:issues)
if current_action?(:show)
"Issue ##{@issue.iid} - #{@issue.title} - " + title
else
"Issues - " + title
end
elsif current_controller?(:blob)
if current_action?(:new) || current_action?(:create)
"New file at #{@ref}"
elsif current_action?(:show)
"#{@blob.path} at #{@ref}"
elsif @blob
"Edit file #{@blob.path} at #{@ref}"
end
elsif current_controller?(:commits)
"Commits at #{@ref} - " + title
elsif current_controller?(:merge_requests)
if current_action?(:show)
"Merge request ##{@merge_request.iid} - " + title
else
"Merge requests - " + title
end
elsif current_controller?(:wikis)
"Wiki - " + title
elsif current_controller?(:network)
"Network graph - " + title
elsif current_controller?(:graphs)
"Graphs - " + title
else
title
end
title
end
def default_url_to_repo(project = nil)
project = project || @project
current_user ? project.url_to_repo : project.http_url_to_repo
......
......@@ -2,8 +2,8 @@ module SubmoduleHelper
include Gitlab::ShellAdapter
# links to files listing for submodule if submodule is a project on this server
def submodule_links(submodule_item, ref = nil)
url = @repository.submodule_url_for(ref, submodule_item.path)
def submodule_links(submodule_item, ref = nil, repository = @repository)
url = repository.submodule_url_for(ref, submodule_item.path)
return url, nil unless url =~ /([^\/:]+)\/([^\/]+\.git)\Z/
......@@ -63,7 +63,7 @@ module SubmoduleHelper
namespace = components.pop.gsub(/^\.\.$/, '')
if namespace.empty?
namespace = @project.group.path
namespace = @project.namespace.name
end
[
......
......@@ -47,7 +47,7 @@ module VisibilityLevelHelper
haml_tag :span do
case level
when Gitlab::VisibilityLevel::PRIVATE
haml_concat "The snippet is visible only for me"
haml_concat "The snippet is visible only for me."
when Gitlab::VisibilityLevel::INTERNAL
haml_concat "The snippet is visible for any logged in user."
when Gitlab::VisibilityLevel::PUBLIC
......
......@@ -6,6 +6,8 @@ module WikiHelper
case wiki_page
when Symbol
wiki_page
when String
wiki_page
else
wiki_page.slug
end
......
class DeviseMailer < Devise::Mailer
default from: "GitLab <#{Gitlab.config.gitlab.email_from}>"
default reply_to: Gitlab.config.gitlab.email_reply_to
end
......@@ -17,11 +17,6 @@ class Notify < ActionMailer::Base
attr_accessor :current_user
helper_method :current_user, :can?
default_url_options[:host] = Gitlab.config.gitlab.host
default_url_options[:protocol] = Gitlab.config.gitlab.protocol
default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port?
default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root
default from: Proc.new { default_sender_address.format }
default reply_to: Gitlab.config.gitlab.email_reply_to
......@@ -70,7 +65,7 @@ class Notify < ActionMailer::Base
# Only the displayed name changes; the actual email address is always the same.
def sender(sender_id, send_from_user_email = false)
return unless sender = User.find(sender_id)
address = default_sender_address
address.display_name = sender.name
......
......@@ -2,13 +2,11 @@
#
# Table name: application_settings
#
# id :integer not null, primary key
# id :integer not null, primary key
# default_projects_limit :integer
# default_branch_protection :integer
# signup_enabled :boolean
# signin_enabled :boolean
# gravatar_enabled :boolean
# twitter_sharing_enabled :boolean
# sign_in_text :text
# created_at :datetime
# updated_at :datetime
......@@ -17,13 +15,16 @@
# twitter_sharing_enabled :boolean default(TRUE)
# help_text :text
# restricted_visibility_levels :text
# max_attachment_size :integer default(10)
# max_attachment_size :integer default(10), not null
# default_project_visibility :integer
# default_snippet_visibility :integer
# restricted_signup_domains :text
#
class ApplicationSetting < ActiveRecord::Base
serialize :restricted_visibility_levels
serialize :restricted_signup_domains, Array
attr_accessor :restricted_signup_domains_raw
validates :home_page_url,
allow_blank: true,
......@@ -56,11 +57,29 @@ class ApplicationSetting < ActiveRecord::Base
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level']
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
restricted_signup_domains: Settings.gitlab['restricted_signup_domains']
)
end
def home_page_url_column_exist
ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
end
def restricted_signup_domains_raw
self.restricted_signup_domains.join("\n") unless self.restricted_signup_domains.nil?
end
def restricted_signup_domains_raw=(values)
self.restricted_signup_domains = []
self.restricted_signup_domains = values.split(
/\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace
| # or
\s # any whitespace character
| # or
[\r\n] # any number of newline characters
/x)
self.restricted_signup_domains.reject! { |d| d.empty? }
end
end
......@@ -7,10 +7,10 @@
# created_at :datetime
# updated_at :datetime
# key :text
# public :boolean default(FALSE)
# title :string(255)
# type :string(255)
# fingerprint :string(255)
# public :boolean default(FALSE), not null
#
class DeployKey < Key
......
......@@ -18,7 +18,6 @@ class Email < ActiveRecord::Base
validates :email, presence: true, email: { strict_mode: true }, uniqueness: true
validate :unique_email, if: ->(email) { email.email_changed? }
after_create :notify
before_validation :cleanup_email
def cleanup_email
......@@ -28,8 +27,4 @@ class Email < ActiveRecord::Base
def unique_email
self.errors.add(:email, 'has already been taken') if User.exists?(email: self.email)
end
def notify
NotificationService.new.new_email(self)
end
end
......@@ -15,6 +15,10 @@ class ExternalIssue
@issue_identifier.to_s
end
def title
"External Issue #{self}"
end
def ==(other)
other.is_a?(self.class) && (to_s == other.to_s)
end
......
......@@ -30,15 +30,12 @@ class WebHook < ActiveRecord::Base
validates :url, presence: true,
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
def execute(data, hook_name)
def execute(data)
parsed_url = URI.parse(url)
if parsed_url.userinfo.blank?
WebHook.post(url,
body: data.to_json,
headers: {
"Content-Type" => "application/json",
"X-Gitlab-Event" => hook_name.singularize.titleize
},
headers: { "Content-Type" => "application/json" },
verify: false)
else
post_url = url.gsub("#{parsed_url.userinfo}@", "")
......@@ -48,10 +45,7 @@ class WebHook < ActiveRecord::Base
}
WebHook.post(post_url,
body: data.to_json,
headers: {
"Content-Type" => "application/json",
"X-Gitlab-Event" => hook_name.singularize.titleize
},
headers: { "Content-Type" => "application/json" },
verify: false,
basic_auth: auth)
end
......@@ -60,7 +54,7 @@ class WebHook < ActiveRecord::Base
false
end
def async_execute(data, hook_name)
Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data, hook_name)
def async_execute(data)
Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data)
end
end
......@@ -10,6 +10,7 @@
# title :string(255)
# type :string(255)
# fingerprint :string(255)
# public :boolean default(FALSE), not null
#
require 'digest/md5'
......
......@@ -6,14 +6,14 @@
# access_level :integer not null
# source_id :integer not null
# source_type :string(255) not null
# user_id :integer not null
# user_id :integer
# notification_level :integer not null
# type :string(255)
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
# invite_email :string
# invite_token :string
# invite_email :string(255)
# invite_token :string(255)
# invite_accepted_at :datetime
#
......
......@@ -6,11 +6,15 @@
# access_level :integer not null
# source_id :integer not null
# source_type :string(255) not null
# user_id :integer not null
# user_id :integer
# notification_level :integer not null
# type :string(255)
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
# invite_email :string(255)
# invite_token :string(255)
# invite_accepted_at :datetime
#
class GroupMember < Member
......
......@@ -6,11 +6,15 @@
# access_level :integer not null
# source_id :integer not null
# source_type :string(255) not null
# user_id :integer not null
# user_id :integer
# notification_level :integer not null
# type :string(255)
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
# invite_email :string(255)
# invite_token :string(255)
# invite_accepted_at :datetime
#
class ProjectMember < Member
......
......@@ -202,6 +202,8 @@ class MergeRequest < ActiveRecord::Base
end
def automerge!(current_user, commit_message = nil)
return unless automergeable?
MergeRequests::AutoMergeService.
new(target_project, current_user).
execute(self, commit_message)
......@@ -211,6 +213,22 @@ class MergeRequest < ActiveRecord::Base
opened? || reopened?
end
def work_in_progress?
title =~ /\A\[?WIP\]?:? /i
end
def automergeable?
open? && !work_in_progress? && can_be_merged?
end
def automerge_status
if work_in_progress?
"work_in_progress"
else
merge_status_name
end
end
def mr_and_commit_notes
# Fetch comments only from last 100 commits
commits_for_notes_limit = 100
......
......@@ -334,14 +334,18 @@ class Project < ActiveRecord::Base
self.id
end
def issue_exists?(issue_id)
def get_issue(issue_id)
if default_issues_tracker?
self.issues.where(iid: issue_id).first.present?
issues.find_by(iid: issue_id)
else
true
ExternalIssue.new(issue_id, self)
end
end
def issue_exists?(issue_id)
get_issue(issue_id)
end
def default_issue_tracker
gitlab_issue_tracker_service || create_gitlab_issue_tracker_service
end
......@@ -355,11 +359,7 @@ class Project < ActiveRecord::Base
end
def default_issues_tracker?
if external_issue_tracker
false
else
true
end
!external_issue_tracker
end
def external_issues_trackers
......@@ -496,7 +496,7 @@ class Project < ActiveRecord::Base
def execute_hooks(data, hooks_scope = :push_hooks)
hooks.send(hooks_scope).each do |hook|
hook.async_execute(data, hooks_scope.to_s)
hook.async_execute(data)
end
if group
group.hooks.send(hooks_scope).each do |hook|
......
# == Schema Information
#
# Table name: project_import_datas
# Table name: project_import_data
#
# id :integer not null, primary key
# project_id :integer
# data :text
# id :integer not null, primary key
# project_id :integer
# data :text
#
require 'carrierwave/orm/activerecord'
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
# Base class for CI services
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
class CustomIssueTrackerService < IssueTrackerService
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
class EmailsOnPushService < Service
......
......@@ -2,14 +2,20 @@
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
class ExternalWikiService < Service
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
require "flowdock-git-hook"
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
require "gemnasium/gitlab_service"
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
class GitlabCiService < CiService
......
......@@ -21,11 +21,6 @@
class GitlabIssueTrackerService < IssueTrackerService
include Rails.application.routes.url_helpers
default_url_options[:host] = Gitlab.config.gitlab.host
default_url_options[:protocol] = Gitlab.config.gitlab.protocol
default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port?
default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
def default?
......
......@@ -15,12 +15,13 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
class HipchatService < Service
MAX_COMMITS = 3
prop_accessor :token, :room, :server, :notify, :color
prop_accessor :token, :room, :server, :notify, :color, :api_version
validates :token, presence: true, if: :activated?
def title
......@@ -41,6 +42,8 @@ class HipchatService < Service
{ type: 'text', name: 'room', placeholder: 'Room name or ID' },
{ type: 'checkbox', name: 'notify' },
{ type: 'select', name: 'color', choices: ['yellow', 'red', 'green', 'purple', 'gray', 'random'] },
{ type: 'text', name: 'api_version',
placeholder: 'Leave blank for default (v2)' },
{ type: 'text', name: 'server',
placeholder: 'Leave blank for default. https://hipchat.example.com' }
]
......@@ -60,7 +63,7 @@ class HipchatService < Service
private
def gate
options = { api_version: 'v2' }
options = { api_version: api_version || 'v2' }
options[:server_url] = server unless server.blank?
@gate ||= HipChat::Client.new(token, options)
end
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
require 'uri'
......
......@@ -15,6 +15,7 @@
# issues_events :boolean default(TRUE)
# merge_requests_events :boolean default(TRUE)
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
#
# To add new service you should build a class inherited from Service
......
......@@ -49,6 +49,7 @@
# password_automatically_set :boolean default(FALSE)
# bitbucket_access_token :string(255)
# bitbucket_access_token_secret :string(255)
# location :string(255)
# public_email :string(255) default(""), not null
#
......@@ -139,13 +140,16 @@ class User < ActiveRecord::Base
validate :avatar_type, if: ->(user) { user.avatar_changed? }
validate :unique_email, if: ->(user) { user.email_changed? }
validate :owns_notification_email, if: ->(user) { user.notification_email_changed? }
validate :owns_public_email, if: ->(user) { user.public_email_changed? }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
before_validation :generate_password, on: :create
before_validation :restricted_signup_domains, on: :create
before_validation :sanitize_attrs
before_validation :set_notification_email, if: ->(user) { user.email_changed? }
before_validation :set_public_email, if: ->(user) { user.public_email_changed? }
after_update :update_emails_with_primary_email, if: ->(user) { user.email_changed? }
before_save :ensure_authentication_token
after_save :ensure_namespace_correct
after_initialize :set_projects_limit
......@@ -303,13 +307,29 @@ class User < ActiveRecord::Base
end
def unique_email
self.errors.add(:email, 'has already been taken') if Email.exists?(email: self.email)
if !self.emails.exists?(email: self.email) && Email.exists?(email: self.email)
self.errors.add(:email, 'has already been taken')
end
end
def owns_notification_email
self.errors.add(:notification_email, "is not an email you own") unless self.all_emails.include?(self.notification_email)
end
def owns_public_email
self.errors.add(:public_email, "is not an email you own") unless self.all_emails.include?(self.public_email)
end
def update_emails_with_primary_email
primary_email_record = self.emails.find_by(email: self.email)
if primary_email_record
primary_email_record.destroy
self.emails.create(email: self.email_was)
self.update_secondary_emails!
end
end
# Groups user has access to
def authorized_groups
@authorized_groups ||= begin
......@@ -476,10 +496,16 @@ class User < ActiveRecord::Base
def set_public_email
if self.public_email.blank? || !self.all_emails.include?(self.public_email)
self.public_email = ''
self.public_email = nil
end
end
def update_secondary_emails!
self.set_notification_email
self.set_public_email
self.save if self.notification_email_changed? || self.public_email_changed?
end
def set_projects_limit
connection_default_value_defined = new_record? && !projects_limit_changed?
return unless self.projects_limit.nil? || connection_default_value_defined
......@@ -643,4 +669,27 @@ class User < ActiveRecord::Base
select(:project_id).
uniq.map(&:project_id)
end
def restricted_signup_domains
email_domains = current_application_settings.restricted_signup_domains
unless email_domains.blank?
match_found = email_domains.any? do |domain|
escaped = Regexp.escape(domain).gsub('\*','.*?')
regexp = Regexp.new "^#{escaped}$", Regexp::IGNORECASE
email_domain = Mail::Address.new(self.email).domain
email_domain =~ regexp
end
unless match_found
self.errors.add :email,
'is not whitelisted. ' +
'Email domains valid for registration are: ' +
email_domains.join(', ')
return false
end
end
true
end
end
......@@ -7,12 +7,12 @@ class SystemHooksService
def execute_hooks(data)
SystemHook.all.each do |sh|
async_execute_hook(sh, data, 'system_hooks')
async_execute_hook sh, data
end
end
def async_execute_hook(hook, data, hook_name)
Sidekiq::Client.enqueue(SystemHookWorker, hook.id, data, hook_name)
def async_execute_hook(hook, data)
Sidekiq::Client.enqueue(SystemHookWorker, hook.id, data)
end
def build_event_data(model, event)
......
class TestHookService
def execute(hook, current_user)
data = Gitlab::PushDataBuilder.build_sample(project(hook), current_user)
hook.execute(data, 'push_hooks')
hook.execute(data)
end
private
......
- page_title "Preview | Appearance"
%h3.page-title
Appearance settings - Preview
%hr
......
- page_title "Appearance"
%h3.page-title
Appearance settings
%p.light
......
......@@ -42,11 +42,11 @@
= f.label :default_branch_protection, class: 'control-label col-sm-2'
.col-sm-10
= f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control'
.form-group
.form-group.project-visibility-level-holder
= f.label :default_project_visibility, class: 'control-label col-sm-2'
.col-sm-10
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: 'Project')
.form-group
.form-group.project-visibility-level-holder
= f.label :default_snippet_visibility, class: 'control-label col-sm-2'
.col-sm-10
= render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: 'Snippet')
......@@ -77,6 +77,11 @@
= f.label :max_attachment_size, 'Maximum attachment size (MB)', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :max_attachment_size, class: 'form-control'
.form-group
= f.label :restricted_signup_domains, 'Restricted domains for sign-ups', class: 'control-label col-sm-2'
.col-sm-10
= f.text_area :restricted_signup_domains_raw, placeholder: 'domain.com', class: 'form-control'
.help-block Ex: domain.com, *.domain.com. Wildcards allowed. Use separate lines for multiple entries.
.form-actions
= f.submit 'Save', class: 'btn btn-primary'
- page_title "Settings"
%h3.page-title Application settings
%hr
= render 'form'
- page_title "Edit", @application.name, "Applications"
%h3.page-title Edit application
- @url = admin_application_path(@application)
= render 'form', application: @application
\ No newline at end of file
= render 'form', application: @application
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.
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.
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