mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-20 10:06:04 +10:00
Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce-to-ee
Conflicts: Gemfile.lock app/controllers/admin/application_settings_controller.rb app/controllers/groups/application_controller.rb app/controllers/groups/group_members_controller.rb app/controllers/projects/team_members_controller.rb app/helpers/application_settings_helper.rb app/helpers/projects_helper.rb app/helpers/tab_helper.rb app/models/application_setting.rb app/models/user.rb app/views/devise/shared/_signin_box.html.haml app/views/groups/projects.html.haml app/views/profiles/keys/_key.html.haml app/views/projects/team_members/_form.html.haml app/views/projects/team_members/index.html.haml config/routes.rb db/schema.rb spec/lib/gitlab/ldap/access_spec.rb
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 7.9.0 (unreleased)
|
||||
- Add HipChat integration documentation (Stan Hu)
|
||||
- Update documentation for object_kind field in Webhook push and tag push Webhooks (Stan Hu)
|
||||
- Fix broken email images (Hannes Rosenögger)
|
||||
- Automatically config git if user forgot, where possible (Zeger-Jan van de Weg)
|
||||
- Fix mass SQL statements on initial push (Hannes Rosenögger)
|
||||
- Add tag push notifications and normalize HipChat and Slack messages to be consistent (Stan Hu)
|
||||
- Add comment notification events to HipChat and Slack services (Stan Hu)
|
||||
@@ -13,6 +17,8 @@ v 7.9.0 (unreleased)
|
||||
- Improve error messages for file edit failures
|
||||
- Improve UI for commits, issues and merge request lists
|
||||
- Fix commit comments on first line of diff not rendering in Merge Request Discussion view.
|
||||
- Allow admins to override restricted project visibility settings.
|
||||
- Move restricted visibility settings from gitlab.yml into the web UI.
|
||||
- Improve trigger merge request hook when source project branch has been updated (Kirill Zaitsev)
|
||||
- Save web edit in new branch
|
||||
- Fix ordering of imported but unchanged projects (Marco Wessel)
|
||||
@@ -21,11 +27,13 @@ v 7.9.0 (unreleased)
|
||||
- Fix checkbox alignment on the application settings page.
|
||||
- Generalize image upload in drag and drop in markdown to all files (Hannes Rosenögger)
|
||||
- Fix mass-unassignment of issues (Robert Speicher)
|
||||
- Fix hidden diff comments in merge request discussion view
|
||||
- Allow user confirmation to be skipped for new users via API
|
||||
- Add a service to send updates to an Irker gateway (Romain Coltel)
|
||||
- Ignore case of LDAP user DN when checking group membership.
|
||||
- Add brakeman (security scanner for Ruby on Rails)
|
||||
- Slack username and channel options
|
||||
- Restrict permissions on backup files
|
||||
- Add grouped milestones from all projects to dashboard.
|
||||
- Web hook sends pusher email as well as commiter
|
||||
- Add Bitbucket omniauth provider.
|
||||
@@ -35,16 +43,16 @@ v 7.9.0 (unreleased)
|
||||
- Send notifications and leave system comments when bulk updating issues.
|
||||
- Automatically link commit ranges to compare page: sha1...sha4 or sha1..sha4 (includes sha1 in comparison)
|
||||
- Move groups page from profile to dashboard
|
||||
- Starred projects page at dashboard
|
||||
- Starred projects page at dashboard
|
||||
- Blocking user does not remove him/her from project/groups but show blocked label
|
||||
- Change subject of EmailsOnPush emails to include namespace, project and branch.
|
||||
- Change subject of EmailsOnPush emails to include first commit message when multiple were pushed.
|
||||
- Remove confusing footer from EmailsOnPush mail body.
|
||||
- Add list of changed files to EmailsOnPush emails.
|
||||
- Add option to send EmailsOnPush emails from committer email if domain matches.
|
||||
- Add list of changed files to EmailsOnPush emails.
|
||||
- Add option to send EmailsOnPush emails from committer email if domain matches.
|
||||
- Add option to disable code diffs in EmailOnPush emails.
|
||||
- Wrap commit message in EmailsOnPush email.
|
||||
- Send EmailsOnPush emails when deleting commits using force push.
|
||||
- Send EmailsOnPush emails when deleting commits using force push.
|
||||
- Fix EmailsOnPush email comparison link to include first commit.
|
||||
- Fix highliht of selected lines in file
|
||||
- Reject access to group/project avatar if the user doesn't have access.
|
||||
@@ -54,6 +62,20 @@ v 7.9.0 (unreleased)
|
||||
- Make email display name configurable
|
||||
- Improve json validation in hook data
|
||||
- Use Emoji One
|
||||
- Updated emoji help documentation to properly reference EmojiOne.
|
||||
- Fix missing GitHub organisation repositories on import page.
|
||||
- Added blue theme
|
||||
- Remove annoying notice messages when create/update merge request
|
||||
- Allow smb:// links in Markdown text.
|
||||
- Filter merge request by title or description at Merge Requests page
|
||||
- Block user if he/she was blocked in Active Directory
|
||||
- Fix import pages not working after first load.
|
||||
- Use custom LDAP label in LDAP signin form.
|
||||
- Execute hooks and services when branch or tag is created or deleted through web interface.
|
||||
- Block and unblock user if he/she was blocked/unblocked in Active Directory
|
||||
- Raise recommended number of unicorn workers from 2 to 3
|
||||
- Use same layout and interactivity for project members as group members.
|
||||
- Prevent gitlab-shell character encoding issues by receiving its changes as raw data.
|
||||
|
||||
v 7.8.4
|
||||
- Fix issue_tracker_id substitution in custom issue trackers
|
||||
@@ -61,7 +83,6 @@ v 7.8.4
|
||||
|
||||
v 7.8.3
|
||||
- Bump version of gitlab_git fixing annotated tags without message
|
||||
- Allow smb:// links in Markdown text.
|
||||
|
||||
v 7.8.2
|
||||
- Fix service migration issue when upgrading from versions prior to 7.3
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.5.4
|
||||
2.6.0
|
||||
|
||||
@@ -39,7 +39,7 @@ gem "browser"
|
||||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '7.1.0'
|
||||
gem "gitlab_git", '~> 7.1.0'
|
||||
|
||||
# Ruby/Rack Git Smart-HTTP Server Handler
|
||||
gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack'
|
||||
@@ -179,6 +179,9 @@ gem 'ace-rails-ap'
|
||||
# Keyboard shortcuts
|
||||
gem 'mousetrap-rails'
|
||||
|
||||
# Detect and convert string character encoding
|
||||
gem 'charlock_holmes'
|
||||
|
||||
# Shutting down requests that take too long
|
||||
gem "slowpoke"
|
||||
|
||||
@@ -270,7 +273,6 @@ end
|
||||
|
||||
group :production do
|
||||
gem "gitlab_meta", '7.0'
|
||||
gem "therubyracer"
|
||||
end
|
||||
|
||||
gem "newrelic_rpm"
|
||||
|
||||
+2
-7
@@ -321,7 +321,6 @@ GEM
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.1.2)
|
||||
launchy (~> 2.2)
|
||||
libv8 (3.16.14.3)
|
||||
listen (2.3.1)
|
||||
celluloid (>= 0.15.2)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
@@ -480,7 +479,6 @@ GEM
|
||||
redis-store (~> 1.1.0)
|
||||
redis-store (1.1.4)
|
||||
redis (>= 2.2)
|
||||
ref (1.0.5)
|
||||
request_store (1.0.5)
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
@@ -605,9 +603,6 @@ GEM
|
||||
tins (~> 0.8)
|
||||
terminal-table (1.4.5)
|
||||
test_after_commit (0.2.2)
|
||||
therubyracer (0.12.0)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
thin (1.6.1)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 1.0.0)
|
||||
@@ -689,6 +684,7 @@ DEPENDENCIES
|
||||
cal-heatmap-rails (~> 0.0.1)
|
||||
capybara (~> 2.2.1)
|
||||
carrierwave
|
||||
charlock_holmes
|
||||
coffee-rails
|
||||
colored
|
||||
coveralls
|
||||
@@ -714,7 +710,7 @@ DEPENDENCIES
|
||||
gitlab-grack (~> 2.0.0.rc2)
|
||||
gitlab-linguist (~> 3.0.1)
|
||||
gitlab_emoji (~> 0.1)
|
||||
gitlab_git (= 7.1.0)
|
||||
gitlab_git (~> 7.1.0)
|
||||
gitlab_meta (= 7.0)
|
||||
gitlab_omniauth-ldap (= 1.2.0)
|
||||
gollum-lib (~> 4.0.0)
|
||||
@@ -795,7 +791,6 @@ DEPENDENCIES
|
||||
stamp
|
||||
state_machine
|
||||
test_after_commit
|
||||
therubyracer
|
||||
thin
|
||||
tinder (~> 1.9.2)
|
||||
turbolinks
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
GitLab is a fast moving and evolving project. We currently don't have the resources to support many releases concurrently. We support exactly one stable release at any given time.
|
||||
|
||||
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)`.
|
||||
GitLab follows the [Semantic Versioning](http://semver.org/) for its releases: `(Major).(Minor).(Patch)` in a [pragmatic way](https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e).
|
||||
|
||||
- **Major version**: Whenever there is something significant or any backwards incompatible changes are introduced to the public API.
|
||||
- **Minor version**: When new, backwards compatible functionality is introduced to the public API or a minor feature is introduced, or when a set of smaller features is rolled out.
|
||||
|
||||
@@ -52,6 +52,7 @@ class Dispatcher
|
||||
new ZenMode()
|
||||
when 'projects:merge_requests:index'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
MergeRequests.init()
|
||||
when 'dashboard:show'
|
||||
new Dashboard()
|
||||
new Activities()
|
||||
@@ -72,9 +73,12 @@ class Dispatcher
|
||||
new Activities()
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
new ProjectsList()
|
||||
when 'groups:members'
|
||||
when 'groups:group_members:index'
|
||||
new GroupMembers()
|
||||
new UsersSelect()
|
||||
when 'projects:project_members:index'
|
||||
new ProjectMembers()
|
||||
new UsersSelect()
|
||||
when 'groups:new', 'groups:edit', 'admin:groups:edit'
|
||||
new GroupAvatar()
|
||||
when 'projects:tree:show'
|
||||
@@ -130,9 +134,8 @@ class Dispatcher
|
||||
new DropzoneInput($('.wiki-form'))
|
||||
when 'snippets', 'labels', 'graphs'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
when 'team_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
|
||||
when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
new UsersSelect()
|
||||
|
||||
|
||||
# If we haven't installed a custom shortcut handler, install the default one
|
||||
|
||||
@@ -16,20 +16,20 @@ class @ImporterStatus
|
||||
$(".js-import-all").click (event) =>
|
||||
$(".js-add-to-import").each ->
|
||||
$(this).click()
|
||||
|
||||
|
||||
setAutoUpdate: ->
|
||||
setInterval (=>
|
||||
$.get @jobs_url, (data) =>
|
||||
$.each data, (i, job) =>
|
||||
job_item = $("#project_" + job.id)
|
||||
status_field = job_item.find(".job-status")
|
||||
|
||||
|
||||
if job.import_status == 'finished'
|
||||
job_item.removeClass("active").addClass("success")
|
||||
status_field.html('<span class="cgreen"><i class="fa fa-check"></i> done</span>')
|
||||
status_field.html('<span><i class="fa fa-check"></i> done</span>')
|
||||
else if job.import_status == 'started'
|
||||
status_field.html("<i class='fa fa-spinner fa-spin'></i> started")
|
||||
else
|
||||
status_field.html(job.import_status)
|
||||
|
||||
), 4000
|
||||
|
||||
), 4000
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
initSearch: ->
|
||||
@timer = null
|
||||
$("#issue_search").keyup ->
|
||||
clearTimeout(@timer);
|
||||
clearTimeout(@timer)
|
||||
@timer = setTimeout(Issues.filterResults, 500)
|
||||
|
||||
filterResults: =>
|
||||
|
||||
@@ -1,8 +1,35 @@
|
||||
#
|
||||
# * Filter merge requests
|
||||
#
|
||||
@merge_requestsPage = ->
|
||||
$('#assignee_id').select2()
|
||||
$('#milestone_id').select2()
|
||||
$('#milestone_id, #assignee_id').on 'change', ->
|
||||
$(this).closest('form').submit()
|
||||
@MergeRequests =
|
||||
init: ->
|
||||
MergeRequests.initSearch()
|
||||
|
||||
# Make sure we trigger ajax request only after user stop typing
|
||||
initSearch: ->
|
||||
@timer = null
|
||||
$("#issue_search").keyup ->
|
||||
clearTimeout(@timer)
|
||||
@timer = setTimeout(MergeRequests.filterResults, 500)
|
||||
|
||||
filterResults: =>
|
||||
form = $("#issue_search_form")
|
||||
search = $("#issue_search").val()
|
||||
$('.merge-requests-holder').css("opacity", '0.5')
|
||||
issues_url = form.attr('action') + '? '+ form.serialize()
|
||||
|
||||
$.ajax
|
||||
type: "GET"
|
||||
url: form.attr('action')
|
||||
data: form.serialize()
|
||||
complete: ->
|
||||
$('.merge-requests-holder').css("opacity", '1.0')
|
||||
success: (data) ->
|
||||
$('.merge-requests-holder').html(data.html)
|
||||
# Change url so if user reload a page - search results are saved
|
||||
History.replaceState {page: issues_url}, document.title, issues_url
|
||||
MergeRequests.reload()
|
||||
dataType: "json"
|
||||
|
||||
reload: ->
|
||||
$('#filter_issue_search').val($('#issue_search').val())
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class @ProjectMembers
|
||||
constructor: ->
|
||||
$('li.project_member').bind 'ajax:success', ->
|
||||
$(this).fadeOut()
|
||||
@@ -152,12 +152,9 @@
|
||||
*/
|
||||
.panel {
|
||||
.panel-heading {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
|
||||
.panel-head-actions {
|
||||
position: relative;
|
||||
top: -6px;
|
||||
top: -5px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
@@ -190,6 +187,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.panel-succes .panel-heading,
|
||||
.panel-info .panel-heading,
|
||||
.panel-danger .panel-heading,
|
||||
.panel-warning .panel-heading,
|
||||
.panel-primary .panel-heading,
|
||||
.alert {
|
||||
a {
|
||||
@extend .alert-link;
|
||||
@@ -197,3 +199,50 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
// Typography =================================================================
|
||||
|
||||
.text-primary,
|
||||
.text-primary:hover {
|
||||
color: $brand-primary;
|
||||
}
|
||||
|
||||
.text-success,
|
||||
.text-success:hover {
|
||||
color: $brand-success;
|
||||
}
|
||||
|
||||
.text-danger,
|
||||
.text-danger:hover {
|
||||
color: $brand-danger;
|
||||
}
|
||||
|
||||
.text-warning,
|
||||
.text-warning:hover {
|
||||
color: $brand-warning;
|
||||
}
|
||||
|
||||
.text-info,
|
||||
.text-info:hover {
|
||||
color: $brand-info;
|
||||
}
|
||||
|
||||
// Tables =====================================================================
|
||||
|
||||
table.table {
|
||||
.dropdown-menu a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.success,
|
||||
.warning,
|
||||
.danger,
|
||||
.info {
|
||||
color: #fff;
|
||||
|
||||
a:not(.btn) {
|
||||
text-decoration: underline;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,8 +716,8 @@ $panel-border-radius: 0;
|
||||
// $panel-footer-bg: #f5f5f5
|
||||
|
||||
$panel-default-text: $text-color;
|
||||
// $panel-default-border: #ddd
|
||||
// $panel-default-heading-bg: #f5f5f5
|
||||
$panel-default-border: $border-color;
|
||||
$panel-default-heading-bg: $background-color;
|
||||
|
||||
// $panel-primary-text: #fff
|
||||
// $panel-primary-border: $brand-primary
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
$style_color: #474D57;
|
||||
$hover: #FFF3EB;
|
||||
$box_bg: #F9F9F9;
|
||||
$gl-link-color: #446e9b;
|
||||
$nprogress-color: #c0392b;
|
||||
$gl-font-size: 14px;
|
||||
@@ -9,6 +8,8 @@ $sidebar_width: 230px;
|
||||
$avatar_radius: 50%;
|
||||
$code_font_size: 13px;
|
||||
$code_line_height: 1.5;
|
||||
$border-color: #dce4ec;
|
||||
$background-color: #ECF0F1;
|
||||
|
||||
/*
|
||||
* State colors:
|
||||
|
||||
@@ -21,18 +21,6 @@
|
||||
float: right;
|
||||
}
|
||||
|
||||
&.btn-small {
|
||||
padding: 2px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&.btn-tiny {
|
||||
font-size: 11px;
|
||||
padding: 2px 6px;
|
||||
line-height: 16px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
&.btn-close {
|
||||
color: $gl-danger;
|
||||
border-color: $gl-danger;
|
||||
@@ -84,6 +72,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group-small > .btn { @extend .btn.btn-small; }
|
||||
.btn-group-tiny > .btn { @extend .btn.btn-tiny; }
|
||||
|
||||
@@ -167,7 +167,7 @@ li.note {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.team_member_show {
|
||||
.project_member_show {
|
||||
td:first-child {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
*/
|
||||
.file-holder {
|
||||
border: 1px solid #CCC;
|
||||
border: 1px solid $border-color;
|
||||
margin-bottom: 1em;
|
||||
|
||||
table {
|
||||
@@ -11,34 +11,30 @@
|
||||
}
|
||||
|
||||
.file-title {
|
||||
background: #EEE;
|
||||
border-bottom: 1px solid #CCC;
|
||||
position: relative;
|
||||
background: $background-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
padding: 10px 15px;
|
||||
|
||||
.options {
|
||||
.file-actions {
|
||||
float: right;
|
||||
margin-top: -3px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 15px;
|
||||
|
||||
.btn {
|
||||
padding: 0px 10px;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.left-options {
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.file_name {
|
||||
font-weight: bold;
|
||||
padding-left: 3px;
|
||||
font-size: 14px;
|
||||
|
||||
small {
|
||||
color: #888;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.file-content {
|
||||
background: #fff;
|
||||
@@ -119,7 +115,7 @@
|
||||
ol {
|
||||
margin-left: 40px;
|
||||
padding: 10px 0;
|
||||
border-left: 1px solid #CCC;
|
||||
border-left: 1px solid $border-color;
|
||||
margin-bottom: 0;
|
||||
background: white;
|
||||
li {
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
.note-text .code {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
background: $box_bg;
|
||||
background: $background-color;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.select2-container, .select2-container.select2-drop-above {
|
||||
.select2-choice {
|
||||
background: #FFF;
|
||||
border-color: #BBB;
|
||||
border-color: #CCC;
|
||||
padding: 6px 14px;
|
||||
line-height: 1.42857143;
|
||||
height: auto;
|
||||
|
||||
@@ -9,7 +9,7 @@ table {
|
||||
th {
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #CCC !important;
|
||||
border-bottom: 1px solid $border-color !important;
|
||||
}
|
||||
td {
|
||||
border-color: #F1F1F1 !important;
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
padding: 10px 0;
|
||||
padding: 3px 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.commit-info-row {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
.commits-compare-switch{
|
||||
@extend .btn;
|
||||
background: image-url("switch_icon.png") no-repeat center center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
text-indent: -9999px;
|
||||
float: left;
|
||||
margin-right: 9px;
|
||||
border: 1px solid #DDD;
|
||||
@include border-radius(4px);
|
||||
padding: 4px;
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
|
||||
.lists-separator {
|
||||
margin: 10px 0;
|
||||
border-color: #DDD;
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
.diff-file {
|
||||
border: 1px solid #CCC;
|
||||
border: 1px solid $border-color;
|
||||
margin-bottom: 1em;
|
||||
|
||||
.diff-header {
|
||||
@extend .clearfix;
|
||||
background: #EEE;
|
||||
border-bottom: 1px solid #CCC;
|
||||
padding: 5px 5px 5px 10px;
|
||||
position: relative;
|
||||
background: $background-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
padding: 10px 15px;
|
||||
color: #555;
|
||||
z-index: 10;
|
||||
|
||||
> span {
|
||||
@include str-truncated(65%);
|
||||
font-family: $monospace_font;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.diff-btn-group {
|
||||
float: right;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 15px;
|
||||
|
||||
.btn {
|
||||
background-color: #FFF;
|
||||
padding: 0px 10px;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +92,7 @@
|
||||
background: #F5F5F5;
|
||||
color: rgba(0,0,0,0.3);
|
||||
padding: 0px 5px;
|
||||
border-right: 1px solid #ccc;
|
||||
border-right: 1px solid $border-color;
|
||||
text-align: right;
|
||||
min-width: 35px;
|
||||
max-width: 50px;
|
||||
@@ -136,7 +141,7 @@
|
||||
background: #ffecec;
|
||||
}
|
||||
&.matched {
|
||||
color: #ccc;
|
||||
color: $border-color;
|
||||
background: #fafafa;
|
||||
}
|
||||
&.parallel {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
}
|
||||
}
|
||||
.commit-button-annotation {
|
||||
@extend .alert;
|
||||
@extend .alert-info;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
.project-network {
|
||||
border: 1px solid #CCC;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
.controls {
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #bbb;
|
||||
border-bottom: 1px solid $border-color;
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,8 @@
|
||||
}
|
||||
|
||||
.accept-merge-holder {
|
||||
margin-top: 5px;
|
||||
|
||||
.accept-action {
|
||||
display: inline-block;
|
||||
|
||||
.accept_merge_request {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.accept-control {
|
||||
@@ -123,7 +117,8 @@
|
||||
}
|
||||
|
||||
.mr-state-widget {
|
||||
background: $box_bg;
|
||||
font-size: 13px;
|
||||
background: #F9F9F9;
|
||||
margin-bottom: 20px;
|
||||
color: #666;
|
||||
border: 1px solid #EEE;
|
||||
|
||||
@@ -89,6 +89,11 @@ ul.notes {
|
||||
}
|
||||
}
|
||||
|
||||
// Diff code in discussion view
|
||||
.discussion-body .diff-file .line_content {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.diff-file .notes_holder {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
&.violet {
|
||||
background: #548;
|
||||
}
|
||||
|
||||
&.blue {
|
||||
background: #2980b9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ ul.nav.nav-projects-tabs {
|
||||
}
|
||||
}
|
||||
|
||||
.team_member_row form {
|
||||
.project_member_row form {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
@@ -301,3 +301,8 @@ table.table.protected-branches-list tr.no-border {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.project-import .btn {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Modern GitLab UI theme
|
||||
*/
|
||||
.ui_blue {
|
||||
@include dark-theme(#BECDE9, #2980b9, #1970a9, #096099);
|
||||
}
|
||||
@@ -20,6 +20,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||
end
|
||||
|
||||
def application_setting_params
|
||||
restricted_levels = params[:application_setting][:restricted_visibility_levels]
|
||||
if restricted_levels.nil?
|
||||
params[:application_setting][:restricted_visibility_levels] = []
|
||||
else
|
||||
restricted_levels.map! do |level|
|
||||
level.to_i
|
||||
end
|
||||
end
|
||||
|
||||
params.require(:application_setting).permit(
|
||||
:default_projects_limit,
|
||||
:default_branch_protection,
|
||||
@@ -29,7 +38,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||
:twitter_sharing_enabled,
|
||||
:sign_in_text,
|
||||
:home_page_url,
|
||||
:help_text
|
||||
:help_text,
|
||||
restricted_visibility_levels: []
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
class Admin::GroupsController < Admin::ApplicationController
|
||||
before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
|
||||
before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :members_update]
|
||||
|
||||
def index
|
||||
@groups = Group.all
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.search(params[:name]) if params[:name].present?
|
||||
@groups = @groups.page(params[:page]).per(20)
|
||||
@groups = @groups.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page]).per(30)
|
||||
@projects = @group.projects.page(params[:projects_page]).per(30)
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page]).per(PER_PAGE)
|
||||
@projects = @group.projects.page(params[:projects_page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def new
|
||||
@@ -40,7 +40,7 @@ class Admin::GroupsController < Admin::ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def project_teams_update
|
||||
def members_update
|
||||
@group.add_users(params[:user_ids].split(','), params[:access_level])
|
||||
|
||||
redirect_to [:admin, @group], notice: 'Users were successfully added.'
|
||||
|
||||
@@ -11,15 +11,15 @@ class Admin::ProjectsController < Admin::ApplicationController
|
||||
@projects = @projects.abandoned if params[:abandoned].present?
|
||||
@projects = @projects.search(params[:name]) if params[:name].present?
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
if @group
|
||||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(30)
|
||||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
@project_members = @project.project_members.page(params[:project_members_page]).per(30)
|
||||
@project_members = @project.project_members.page(params[:project_members_page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def transfer
|
||||
|
||||
@@ -4,6 +4,8 @@ class ApplicationController < ActionController::Base
|
||||
include Gitlab::CurrentSettings
|
||||
include GitlabRoutingHelper
|
||||
|
||||
PER_PAGE = 20
|
||||
|
||||
before_filter :authenticate_user_from_token!
|
||||
before_filter :authenticate_user!
|
||||
before_filter :reject_blocked!
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
class Dashboard::GroupsController < ApplicationController
|
||||
def index
|
||||
@user_groups = current_user.group_members.page(params[:page]).per(20)
|
||||
end
|
||||
|
||||
def leave
|
||||
@users_group = group.group_members.where(user_id: current_user.id).first
|
||||
if can?(current_user, :destroy, @users_group)
|
||||
@users_group.destroy
|
||||
redirect_to(dashboard_groups_path, info: "You left #{group.name} group.")
|
||||
else
|
||||
return render_403
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def group
|
||||
@group ||= Group.find_by(path: params[:id])
|
||||
@group_members = current_user.group_members.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Dashboard::MilestonesController < ApplicationController
|
||||
else state('active')
|
||||
end
|
||||
@dashboard_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(30)
|
||||
@dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -25,13 +25,13 @@ class DashboardController < ApplicationController
|
||||
|
||||
def merge_requests
|
||||
@merge_requests = get_merge_requests_collection
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(20)
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
|
||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||
end
|
||||
|
||||
def issues
|
||||
@issues = get_issues_collection
|
||||
@issues = @issues.page(params[:page]).per(20)
|
||||
@issues = @issues.page(params[:page]).per(PER_PAGE)
|
||||
@issues = @issues.preload(:author, :project)
|
||||
|
||||
respond_to do |format|
|
||||
|
||||
@@ -8,6 +8,6 @@ class Explore::GroupsController < ApplicationController
|
||||
@groups = GroupsFinder.new.execute(current_user)
|
||||
@groups = @groups.search(params[:search]) if params[:search].present?
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.page(params[:page]).per(20)
|
||||
@groups = @groups.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,17 +11,17 @@ class Explore::ProjectsController < ApplicationController
|
||||
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
||||
@projects = @projects.search(params[:search]) if params[:search].present?
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).page(params[:page]).per(20)
|
||||
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def trending
|
||||
@trending_projects = TrendingProjectsFinder.new.execute(current_user)
|
||||
@trending_projects = @trending_projects.page(params[:page]).per(10)
|
||||
@trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def starred
|
||||
@starred_projects = ProjectsFinder.new.execute(current_user)
|
||||
@starred_projects = @starred_projects.reorder('star_count DESC')
|
||||
@starred_projects = @starred_projects.page(params[:page]).per(10)
|
||||
@starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
class Groups::ApplicationController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
|
||||
def authorize_read_group!
|
||||
unless @group and can?(current_user, :read_group, @group)
|
||||
if current_user.nil?
|
||||
return authenticate_user!
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_admin_group!
|
||||
unless can?(current_user, :manage_group, group)
|
||||
return render_404
|
||||
@@ -11,4 +21,12 @@ 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
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
class Groups::GroupMembersController < Groups::ApplicationController
|
||||
skip_before_filter :authenticate_user!, only: [:index]
|
||||
before_filter :group
|
||||
|
||||
# Authorize
|
||||
before_filter :authorize_admin_group!
|
||||
before_filter :authorize_read_group!
|
||||
before_filter :authorize_admin_group!, except: [:index, :leave]
|
||||
|
||||
layout 'group'
|
||||
layout :determine_layout
|
||||
|
||||
def index
|
||||
@project = @group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@members = @group.group_members
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
@members = @members.where(user_id: users)
|
||||
end
|
||||
|
||||
@members = @members.order('access_level DESC').page(params[:page]).per(50)
|
||||
@group_member = GroupMember.new
|
||||
end
|
||||
|
||||
def create
|
||||
access_level = params[:access_level]
|
||||
user_ids = params[:user_ids].split(',')
|
||||
|
||||
@group.add_users(user_ids, access_level)
|
||||
group_members = @group.group_members.where(user_id: user_ids)
|
||||
|
||||
users = User.where(id: user_ids).pluck(:id, :name)
|
||||
users.each do |user|
|
||||
details = {
|
||||
add: "user_access",
|
||||
as: Gitlab::Access.options_with_owner.key(access_level.to_i),
|
||||
target_id: user[0],
|
||||
target_type: "User",
|
||||
target_details: user[1],
|
||||
}
|
||||
AuditEventService.new(current_user, @group, details).security_event
|
||||
group_members.each do |group_member|
|
||||
log_audit_event(group_member, action: :create)
|
||||
end
|
||||
|
||||
redirect_to members_group_path(@group), notice: 'Users were successfully added.'
|
||||
redirect_to group_group_members_path(@group), notice: 'Users were successfully added.'
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -32,36 +40,19 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
||||
old_access_level = @member.human_access
|
||||
|
||||
if @member.update_attributes(member_params)
|
||||
details = {
|
||||
change: "access_level",
|
||||
from: old_access_level,
|
||||
to: @member.human_access,
|
||||
target_id: @member.user_id,
|
||||
target_type: "User",
|
||||
target_details: @member.user.name,
|
||||
}
|
||||
AuditEventService.new(current_user, @group, details).security_event
|
||||
log_audit_event(@member, action: :update, old_access_level: old_access_level)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@users_group = @group.group_members.find(params[:id])
|
||||
@group_member = @group.group_members.find(params[:id])
|
||||
|
||||
if can?(current_user, :destroy, @users_group) # May fail if last owner.
|
||||
user_id = @users_group.id
|
||||
user_name = @users_group.user.name
|
||||
if @users_group.destroy
|
||||
details = {
|
||||
remove: "user_access",
|
||||
target_id: user_id,
|
||||
target_type: "User",
|
||||
target_details: user_name,
|
||||
}
|
||||
AuditEventService.new(current_user, @group, details).security_event
|
||||
end
|
||||
if can?(current_user, :destroy_group_member, @group_member) # May fail if last owner.
|
||||
@group_member.destroy
|
||||
log_audit_event(@group_member, action: :destroy)
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
else
|
||||
@@ -69,9 +60,27 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def leave
|
||||
@group_member = @group.group_members.where(user_id: current_user.id).first
|
||||
|
||||
if can?(current_user, :destroy_group_member, @group_member)
|
||||
@group_member.destroy
|
||||
log_audit_event(@group_member, action: :destroy)
|
||||
|
||||
redirect_to(dashboard_groups_path, info: "You left #{group.name} group.")
|
||||
else
|
||||
return render_403
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def member_params
|
||||
params.require(:group_member).permit(:access_level, :user_id)
|
||||
end
|
||||
|
||||
def log_audit_event(member, options = {})
|
||||
AuditEventService.new(current_user, @group, options).
|
||||
for_member(member).security_event
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ class Groups::MilestonesController < ApplicationController
|
||||
else state('active')
|
||||
end
|
||||
@group_milestones = Milestones::GroupService.new(project_milestones).execute
|
||||
@group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(30)
|
||||
@group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class GroupsController < Groups::ApplicationController
|
||||
skip_before_filter :authenticate_user!, only: [:show, :issues, :members, :merge_requests]
|
||||
skip_before_filter :authenticate_user!, only: [:show, :issues, :merge_requests]
|
||||
respond_to :html
|
||||
before_filter :group, except: [:new, :create]
|
||||
|
||||
@@ -54,13 +54,13 @@ class GroupsController < Groups::ApplicationController
|
||||
|
||||
def merge_requests
|
||||
@merge_requests = get_merge_requests_collection
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(20)
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
|
||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||
end
|
||||
|
||||
def issues
|
||||
@issues = get_issues_collection
|
||||
@issues = @issues.page(params[:page]).per(20)
|
||||
@issues = @issues.page(params[:page]).per(PER_PAGE)
|
||||
@issues = @issues.preload(:author, :project)
|
||||
|
||||
respond_to do |format|
|
||||
@@ -69,19 +69,6 @@ class GroupsController < Groups::ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def members
|
||||
@project = group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@members = group.group_members
|
||||
|
||||
if params[:search].present?
|
||||
users = group.users.search(params[:search]).to_a
|
||||
@members = @members.where(user_id: users)
|
||||
end
|
||||
|
||||
@members = @members.order('access_level DESC').page(params[:page]).per(50)
|
||||
@users_group = GroupMember.new
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class Import::GithubController < Import::BaseController
|
||||
def status
|
||||
@repos = client.repos
|
||||
client.orgs.each do |org|
|
||||
@repos += client.repos(org.login)
|
||||
@repos += client.org_repos(org.login)
|
||||
end
|
||||
|
||||
@already_added_projects = current_user.created_projects.where(import_type: "github")
|
||||
|
||||
@@ -14,9 +14,9 @@ class Profiles::NotificationsController < ApplicationController
|
||||
@saved = if type == 'global'
|
||||
current_user.update_attributes(user_params)
|
||||
elsif type == 'group'
|
||||
users_group = current_user.group_members.find(params[:notification_id])
|
||||
users_group.notification_level = params[:notification_level]
|
||||
users_group.save
|
||||
group_member = current_user.group_members.find(params[:notification_id])
|
||||
group_member.notification_level = params[:notification_level]
|
||||
group_member.save
|
||||
else
|
||||
project_member = current_user.project_members.find(params[:notification_id])
|
||||
project_member.notification_level = params[:notification_level]
|
||||
|
||||
@@ -43,7 +43,7 @@ class ProfilesController < ApplicationController
|
||||
end
|
||||
|
||||
def history
|
||||
@events = current_user.recent_events.page(params[:page]).per(20)
|
||||
@events = current_user.recent_events.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def update_username
|
||||
|
||||
@@ -7,7 +7,7 @@ class Projects::BlameController < Projects::ApplicationController
|
||||
before_filter :authorize_download_code!
|
||||
|
||||
def show
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
@blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
|
||||
@blame = Gitlab::Git::Blame.new(@repository, @commit.id, @path)
|
||||
@blob = @blame.blob
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Projects::BranchesController < Projects::ApplicationController
|
||||
def index
|
||||
@sort = params[:sort] || 'name'
|
||||
@branches = @repository.branches_sorted_by(@sort)
|
||||
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(30)
|
||||
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def recent
|
||||
|
||||
@@ -28,8 +28,8 @@ class Projects::GraphsController < Projects::ApplicationController
|
||||
|
||||
@commits.each do |commit|
|
||||
@log << {
|
||||
author_name: commit.author_name.force_encoding('UTF-8'),
|
||||
author_email: commit.author_email.force_encoding('UTF-8'),
|
||||
author_name: commit.author_name,
|
||||
author_email: commit.author_email,
|
||||
date: commit.committed_date.strftime("%Y-%m-%d")
|
||||
}
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||
terms = params['issue_search']
|
||||
@issues = get_issues_collection
|
||||
@issues = @issues.full_search(terms) if terms.present?
|
||||
@issues = @issues.page(params[:page]).per(20)
|
||||
@issues = @issues.page(params[:page]).per(PER_PAGE)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
@@ -7,7 +7,7 @@ class Projects::LabelsController < Projects::ApplicationController
|
||||
respond_to :js, :html
|
||||
|
||||
def index
|
||||
@labels = @project.labels.page(params[:page]).per(20)
|
||||
@labels = @project.labels.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def new
|
||||
|
||||
@@ -17,8 +17,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
|
||||
|
||||
def index
|
||||
terms = params['issue_search']
|
||||
@merge_requests = get_merge_requests_collection
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(20)
|
||||
@merge_requests = @merge_requests.full_search(terms) if terms.present?
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
render json: {
|
||||
html: view_to_html_string("projects/merge_requests/_merge_requests")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -18,7 +18,7 @@ class Projects::MilestonesController < Projects::ApplicationController
|
||||
end
|
||||
|
||||
@milestones = @milestones.includes(:project)
|
||||
@milestones = @milestones.page(params[:page]).per(20)
|
||||
@milestones = @milestones.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def new
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
class Projects::ProjectMembersController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_filter :authorize_admin_project!, except: :leave
|
||||
|
||||
layout "project_settings"
|
||||
|
||||
def index
|
||||
@project_members = @project.project_members
|
||||
|
||||
if params[:search].present?
|
||||
users = @project.users.search(params[:search]).to_a
|
||||
@project_members = @project_members.where(user_id: users)
|
||||
end
|
||||
|
||||
@project_members = @project_members.order('access_level DESC')
|
||||
|
||||
@group = @project.group
|
||||
if @group
|
||||
@group_members = @group.group_members
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
@group_members = @group_members.where(user_id: users)
|
||||
end
|
||||
|
||||
@group_members = @group_members.order('access_level DESC').limit(20)
|
||||
end
|
||||
|
||||
@project_member = @project.project_members.new
|
||||
@project_group_links = @project.project_group_links
|
||||
end
|
||||
|
||||
def new
|
||||
@project_member = @project.project_members.new
|
||||
end
|
||||
|
||||
def create
|
||||
users = User.where(id: params[:user_ids].split(','))
|
||||
@project.team << [users, params[:access_level]]
|
||||
members = @project.project_members.where(user_id: user_ids)
|
||||
|
||||
members.each do |member|
|
||||
log_audit_event(member, action: :create)
|
||||
end
|
||||
|
||||
redirect_to namespace_project_project_members_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
def update
|
||||
@project_member = @project.project_members.find_by(user_id: member)
|
||||
old_access_level = @project_member.human_access
|
||||
|
||||
if @project_member.update_attributes(member_params)
|
||||
log_audit_event(@project_member, action: :update, old_access_level: old_access_level)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@project_member = @project.project_members.find_by(user_id: member)
|
||||
@project_member.destroy
|
||||
log_audit_event(@project_member, action: :destroy)
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
redirect_to namespace_project_project_members_path(@project.namespace,
|
||||
@project)
|
||||
end
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
def leave
|
||||
@project_member = @project.project_members.find_by(user_id: current_user)
|
||||
@project_member.destroy
|
||||
log_audit_event(@project_member, action: :destroy)
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :back }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
def apply_import
|
||||
giver = Project.find(params[:source_project_id])
|
||||
status = @project.team.import(giver)
|
||||
notice = status ? "Successfully imported" : "Import failed"
|
||||
|
||||
redirect_to(namespace_project_project_members_path(project.namespace, project),
|
||||
notice: notice)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def member
|
||||
@member ||= User.find_by(username: params[:id])
|
||||
end
|
||||
|
||||
def member_params
|
||||
params.require(:project_member).permit(:user_id, :access_level)
|
||||
end
|
||||
|
||||
def log_audit_event(member, options = {})
|
||||
AuditEventService.new(current_user, @project, options).
|
||||
for_member(member).security_event
|
||||
end
|
||||
end
|
||||
@@ -28,26 +28,22 @@ class Projects::SnippetsController < Projects::ApplicationController
|
||||
end
|
||||
|
||||
def create
|
||||
@snippet = @project.snippets.build(snippet_params)
|
||||
@snippet.author = current_user
|
||||
|
||||
if @snippet.save
|
||||
redirect_to namespace_project_snippet_path(@project.namespace, @project,
|
||||
@snippet)
|
||||
else
|
||||
respond_with(@snippet)
|
||||
end
|
||||
@snippet = CreateSnippetService.new(@project, current_user,
|
||||
snippet_params).execute
|
||||
respond_with(@snippet,
|
||||
location: namespace_project_snippet_path(@project.namespace,
|
||||
@project, @snippet))
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @snippet.update_attributes(snippet_params)
|
||||
redirect_to namespace_project_snippet_path(@project.namespace, @project, @snippet)
|
||||
else
|
||||
respond_with(@snippet)
|
||||
end
|
||||
UpdateSnippetService.new(project, current_user, @snippet,
|
||||
snippet_params).execute
|
||||
respond_with(@snippet,
|
||||
location: namespace_project_snippet_path(@project.namespace,
|
||||
@project, @snippet))
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -7,7 +7,7 @@ class Projects::TagsController < Projects::ApplicationController
|
||||
|
||||
def index
|
||||
sorted = VersionSorter.rsort(@repository.tag_names)
|
||||
@tags = Kaminari.paginate_array(sorted).page(params[:page]).per(30)
|
||||
@tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def create
|
||||
@@ -24,14 +24,13 @@ class Projects::TagsController < Projects::ApplicationController
|
||||
end
|
||||
|
||||
def destroy
|
||||
tag = @repository.find_tag(params[:id])
|
||||
|
||||
if tag && @repository.rm_tag(tag.name)
|
||||
EventCreateService.new.push_ref(@project, current_user, tag, 'rm', Gitlab::Git::TAG_REF_PREFIX)
|
||||
end
|
||||
DeleteTagService.new(project, current_user).execute(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to namespace_project_tags_path }
|
||||
format.html do
|
||||
redirect_to namespace_project_tags_path(@project.namespace,
|
||||
@project)
|
||||
end
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
class Projects::TeamMembersController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_filter :authorize_admin_project!, except: :leave
|
||||
|
||||
layout "project_settings"
|
||||
|
||||
def index
|
||||
@group = @project.group
|
||||
@project_members = @project.project_members.order('access_level DESC')
|
||||
@project_group_links = @project.project_group_links
|
||||
end
|
||||
|
||||
def new
|
||||
@user_project_relation = @project.project_members.new
|
||||
end
|
||||
|
||||
def create
|
||||
users = User.where(id: params[:user_ids].split(','))
|
||||
access_level = params[:access_level]
|
||||
@project.team << [users, access_level]
|
||||
|
||||
users.each do |user|
|
||||
details = {
|
||||
add: "user_access",
|
||||
as: Gitlab::Access.options_with_owner.key(access_level.to_i),
|
||||
target_id: user.id,
|
||||
target_type: "User",
|
||||
target_details: user.name,
|
||||
}
|
||||
AuditEventService.new(current_user, @project, details).security_event
|
||||
end
|
||||
|
||||
redirect_to namespace_project_team_index_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
def update
|
||||
@user_project_relation = @project.project_members.find_by(user_id: member)
|
||||
old_access_level = @user_project_relation.human_access
|
||||
|
||||
if @user_project_relation.update_attributes(member_params)
|
||||
details = {
|
||||
change: "access_level",
|
||||
from: old_access_level,
|
||||
to: @user_project_relation.human_access,
|
||||
target_id: @user_project_relation.user_id,
|
||||
target_type: "User",
|
||||
target_details: @user_project_relation.user.name,
|
||||
}
|
||||
AuditEventService.new(current_user, @project, details).security_event
|
||||
end
|
||||
|
||||
unless @user_project_relation.valid?
|
||||
flash[:alert] = "User should have at least one role"
|
||||
end
|
||||
redirect_to namespace_project_team_index_path(@project.namespace, @project)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@user_project_relation = @project.project_members.find_by(user_id: member)
|
||||
user_id = @user_project_relation.user_id
|
||||
user_name = @user_project_relation.user.name
|
||||
|
||||
if @user_project_relation.destroy
|
||||
details = {
|
||||
remove: "user_access",
|
||||
target_id: user_id,
|
||||
target_type: "User",
|
||||
target_details: user_name,
|
||||
}
|
||||
AuditEventService.new(current_user, @project, details).security_event
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
redirect_to namespace_project_team_index_path(@project.namespace,
|
||||
@project)
|
||||
end
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
def leave
|
||||
@project.project_members.find_by(user_id: current_user).destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :back }
|
||||
format.js { render nothing: true }
|
||||
end
|
||||
end
|
||||
|
||||
def apply_import
|
||||
giver = Project.find(params[:source_project_id])
|
||||
status = @project.team.import(giver)
|
||||
notice = status ? "Successfully imported" : "Import failed"
|
||||
|
||||
redirect_to(namespace_project_team_index_path(project.namespace, project),
|
||||
notice: notice)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def member
|
||||
@member ||= User.find_by(username: params[:id])
|
||||
end
|
||||
|
||||
def member_params
|
||||
params.require(:project_member).permit(:user_id, :access_level)
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,7 @@ class Projects::WikisController < Projects::ApplicationController
|
||||
before_filter :load_project_wiki
|
||||
|
||||
def pages
|
||||
@wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]).per(30)
|
||||
@wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -16,7 +16,7 @@ class SnippetsController < ApplicationController
|
||||
layout :determine_layout
|
||||
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(current_user, filter: :all).page(params[:page]).per(20)
|
||||
@snippets = SnippetsFinder.new.execute(current_user, filter: :all).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def user_index
|
||||
@@ -28,7 +28,7 @@ class SnippetsController < ApplicationController
|
||||
filter: :by_user,
|
||||
user: @user,
|
||||
scope: params[:scope] }).
|
||||
page(params[:page]).per(20)
|
||||
page(params[:page]).per(PER_PAGE)
|
||||
|
||||
if @user == current_user
|
||||
render 'current_user_index'
|
||||
@@ -42,25 +42,19 @@ class SnippetsController < ApplicationController
|
||||
end
|
||||
|
||||
def create
|
||||
@snippet = PersonalSnippet.new(snippet_params)
|
||||
@snippet.author = current_user
|
||||
@snippet = CreateSnippetService.new(nil, current_user,
|
||||
snippet_params).execute
|
||||
|
||||
if @snippet.save
|
||||
redirect_to snippet_path(@snippet)
|
||||
else
|
||||
respond_with @snippet
|
||||
end
|
||||
respond_with @snippet.becomes(Snippet)
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @snippet.update_attributes(snippet_params)
|
||||
redirect_to snippet_path(@snippet)
|
||||
else
|
||||
respond_with @snippet
|
||||
end
|
||||
UpdateSnippetService.new(nil, current_user, @snippet,
|
||||
snippet_params).execute
|
||||
respond_with @snippet.becomes(Snippet)
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -86,15 +86,6 @@ module ApplicationHelper
|
||||
end
|
||||
end
|
||||
|
||||
def group_icon(group_path)
|
||||
group = Group.find_by(path: group_path)
|
||||
if group && group.avatar.present?
|
||||
group.avatar.url
|
||||
else
|
||||
image_path('no_group_avatar.png')
|
||||
end
|
||||
end
|
||||
|
||||
def avatar_icon(user_email = '', size = nil)
|
||||
user = User.find_by(email: user_email)
|
||||
|
||||
|
||||
@@ -22,4 +22,21 @@ module ApplicationSettingsHelper
|
||||
def help_text
|
||||
current_application_settings.help_text
|
||||
end
|
||||
|
||||
# Return a group of checkboxes that use Bootstrap's button plugin for a
|
||||
# toggle button effect.
|
||||
def restricted_level_checkboxes(help_block_id)
|
||||
Gitlab::VisibilityLevel.options.map do |name, level|
|
||||
checked = restricted_visibility_levels(true).include?(level)
|
||||
css_class = 'btn btn-primary'
|
||||
css_class += ' active' if checked
|
||||
checkbox_name = 'application_setting[restricted_visibility_levels][]'
|
||||
|
||||
label_tag(checkbox_name, class: css_class) do
|
||||
check_box_tag(checkbox_name, level, checked,
|
||||
autocomplete: 'off',
|
||||
'aria-describedby' => help_block_id) + name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -122,7 +122,7 @@ module DiffHelper
|
||||
params_copy = params.dup
|
||||
params_copy[:view] = 'inline'
|
||||
|
||||
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] != 'parallel' ? 'btn active' : 'btn') do
|
||||
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] != 'parallel' ? 'btn btn-sm active' : 'btn btn-sm') do
|
||||
'Inline'
|
||||
end
|
||||
end
|
||||
@@ -131,7 +131,7 @@ module DiffHelper
|
||||
params_copy = params.dup
|
||||
params_copy[:view] = 'parallel'
|
||||
|
||||
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] == 'parallel' ? 'btn active' : 'btn') do
|
||||
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] == 'parallel' ? 'btn active btn-sm' : 'btn btn-sm') do
|
||||
'Side-by-side'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
require 'html/pipeline'
|
||||
require 'html/pipeline/gitlab'
|
||||
|
||||
module EmailsHelper
|
||||
|
||||
# Google Actions
|
||||
@@ -39,4 +42,26 @@ module EmailsHelper
|
||||
lexer = Rugments::Lexers::Diff.new
|
||||
raw formatter.format(lexer.lex(diffcontent))
|
||||
end
|
||||
|
||||
def replace_image_links_with_base64(text, project)
|
||||
# Used pipelines in GitLab:
|
||||
# GitlabEmailImageFilter - replaces images that have been uploaded as attachments with inline images in emails.
|
||||
#
|
||||
# see https://gitlab.com/gitlab-org/html-pipeline-gitlab for more filters
|
||||
filters = [
|
||||
HTML::Pipeline::Gitlab::GitlabEmailImageFilter
|
||||
]
|
||||
|
||||
context = {
|
||||
base_url: File.join(Gitlab.config.gitlab.url, project.path_with_namespace, 'uploads'),
|
||||
upload_path: File.join(Rails.root, 'public', 'uploads', project.path_with_namespace),
|
||||
}
|
||||
|
||||
pipeline = HTML::Pipeline::Gitlab.new(filters).pipeline
|
||||
|
||||
result = pipeline.call(text, context)
|
||||
text = result[:output].to_html(save_with: 0)
|
||||
|
||||
text.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,7 +45,8 @@ module GitlabRoutingHelper
|
||||
namespace_project_merge_request_url(entity.project.namespace, entity.project, entity, *args)
|
||||
end
|
||||
|
||||
def snippet_url(entity, *args)
|
||||
def project_snippet_url(entity, *args)
|
||||
namespace_project_snippet_url(entity.project.namespace, entity.project, entity, *args)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,4 +42,16 @@ module GroupsHelper
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def group_icon(group)
|
||||
if group.is_a?(String)
|
||||
group = Group.find_by(path: group)
|
||||
end
|
||||
|
||||
if group && group.avatar.present?
|
||||
group.avatar.url
|
||||
else
|
||||
image_path('no_group_avatar.png')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ module NamespacesHelper
|
||||
|
||||
def namespace_icon(namespace, size = 40)
|
||||
if namespace.kind_of?(Group)
|
||||
group_icon(namespace.path)
|
||||
group_icon(namespace)
|
||||
else
|
||||
avatar_icon(namespace.owner.email, size)
|
||||
end
|
||||
|
||||
@@ -60,7 +60,7 @@ module SearchHelper
|
||||
{ label: "#{prefix} - Merge Requests", url: namespace_project_merge_requests_path(@project.namespace, @project) },
|
||||
{ label: "#{prefix} - Milestones", url: namespace_project_milestones_path(@project.namespace, @project) },
|
||||
{ label: "#{prefix} - Snippets", url: namespace_project_snippets_path(@project.namespace, @project) },
|
||||
{ label: "#{prefix} - Team", url: namespace_project_team_index_path(@project.namespace, @project) },
|
||||
{ label: "#{prefix} - Members", url: namespace_project_project_members_path(@project.namespace, @project) },
|
||||
{ label: "#{prefix} - Wiki", url: namespace_project_wikis_path(@project.namespace, @project) },
|
||||
]
|
||||
else
|
||||
|
||||
@@ -89,7 +89,7 @@ module TabHelper
|
||||
def project_tab_class
|
||||
return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
|
||||
|
||||
if ['services', 'git_hooks', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name
|
||||
if ['services', 'git_hooks', 'hooks', 'deploy_keys', 'project_members', 'protected_branches'].include? controller.controller_name
|
||||
"active"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,7 +60,8 @@ module VisibilityLevelHelper
|
||||
Project.visibility_levels.key(level)
|
||||
end
|
||||
|
||||
def restricted_visibility_levels
|
||||
current_user.is_admin? ? [] : gitlab_config.restricted_visibility_levels
|
||||
def restricted_visibility_levels(show_all = false)
|
||||
return [] if current_user.is_admin? && !show_all
|
||||
current_application_settings.restricted_visibility_levels || []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
module Emails
|
||||
module Groups
|
||||
def group_access_granted_email(user_group_id)
|
||||
@membership = GroupMember.find(user_group_id)
|
||||
@group = @membership.group
|
||||
def group_access_granted_email(group_member_id)
|
||||
@group_member = GroupMember.find(group_member_id)
|
||||
@group = @group_member.group
|
||||
@target_url = group_url(@group)
|
||||
mail(to: @membership.user.email,
|
||||
mail(to: @group_member.user.email,
|
||||
subject: subject("Access to group was granted"))
|
||||
end
|
||||
end
|
||||
|
||||
+12
-10
@@ -14,7 +14,7 @@ class Ability
|
||||
when "MergeRequest" then merge_request_abilities(user, subject)
|
||||
when "Group" then group_abilities(user, subject)
|
||||
when "Namespace" then namespace_abilities(user, subject)
|
||||
when "GroupMember" then users_group_abilities(user, subject)
|
||||
when "GroupMember" then group_member_abilities(user, subject)
|
||||
else []
|
||||
end.concat(global_abilities(user))
|
||||
end
|
||||
@@ -37,7 +37,7 @@ class Ability
|
||||
:read_issue,
|
||||
:read_milestone,
|
||||
:read_project_snippet,
|
||||
:read_team_member,
|
||||
:read_project_member,
|
||||
:read_merge_request,
|
||||
:read_note,
|
||||
:download_code
|
||||
@@ -119,7 +119,7 @@ class Ability
|
||||
:read_issue,
|
||||
:read_milestone,
|
||||
:read_project_snippet,
|
||||
:read_team_member,
|
||||
:read_project_member,
|
||||
:read_merge_request,
|
||||
:read_note,
|
||||
:write_project,
|
||||
@@ -166,7 +166,7 @@ class Ability
|
||||
:admin_issue,
|
||||
:admin_milestone,
|
||||
:admin_project_snippet,
|
||||
:admin_team_member,
|
||||
:admin_project_member,
|
||||
:admin_merge_request,
|
||||
:admin_note,
|
||||
:admin_wiki,
|
||||
@@ -225,13 +225,15 @@ class Ability
|
||||
|
||||
[:issue, :note, :project_snippet, :personal_snippet, :merge_request].each do |name|
|
||||
define_method "#{name}_abilities" do |user, subject|
|
||||
if subject.author == user
|
||||
[
|
||||
if subject.author == user || user.is_admin?
|
||||
rules = [
|
||||
:"read_#{name}",
|
||||
:"write_#{name}",
|
||||
:"modify_#{name}",
|
||||
:"admin_#{name}"
|
||||
]
|
||||
rules.push(:change_visibility_level) if subject.is_a?(Snippet)
|
||||
rules
|
||||
elsif subject.respond_to?(:assignee) && subject.assignee == user
|
||||
[
|
||||
:"read_#{name}",
|
||||
@@ -248,17 +250,17 @@ class Ability
|
||||
end
|
||||
end
|
||||
|
||||
def users_group_abilities(user, subject)
|
||||
def group_member_abilities(user, subject)
|
||||
rules = []
|
||||
target_user = subject.user
|
||||
group = subject.group
|
||||
can_manage = group_abilities(user, group).include?(:manage_group)
|
||||
if can_manage && (user != target_user)
|
||||
rules << :modify
|
||||
rules << :destroy
|
||||
rules << :modify_group_member
|
||||
rules << :destroy_group_member
|
||||
end
|
||||
if !group.last_owner?(user) && (can_manage || (user == target_user))
|
||||
rules << :destroy
|
||||
rules << :destroy_group_member
|
||||
end
|
||||
rules
|
||||
end
|
||||
|
||||
@@ -2,28 +2,41 @@
|
||||
#
|
||||
# Table name: application_settings
|
||||
#
|
||||
# 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
|
||||
# home_page_url :string(255)
|
||||
# default_branch_protection :integer default(2)
|
||||
# twitter_sharing_enabled :boolean default(TRUE)
|
||||
# help_text :text
|
||||
# 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
|
||||
# home_page_url :string(255)
|
||||
# default_branch_protection :integer default(2)
|
||||
# twitter_sharing_enabled :boolean default(TRUE)
|
||||
# help_text :text
|
||||
# restricted_visibility_levels :text
|
||||
#
|
||||
|
||||
class ApplicationSetting < ActiveRecord::Base
|
||||
serialize :restricted_visibility_levels
|
||||
|
||||
validates :home_page_url,
|
||||
allow_blank: true,
|
||||
format: { with: URI::regexp(%w(http https)), message: "should be a valid url" },
|
||||
if: :home_page_url_column_exist
|
||||
|
||||
validates_each :restricted_visibility_levels do |record, attr, value|
|
||||
unless value.nil?
|
||||
value.each do |level|
|
||||
unless Gitlab::VisibilityLevel.options.has_value?(level)
|
||||
record.errors.add(attr, "'#{level}' is not a valid visibility level")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.current
|
||||
ApplicationSetting.last
|
||||
end
|
||||
@@ -37,6 +50,7 @@ class ApplicationSetting < ActiveRecord::Base
|
||||
twitter_sharing_enabled: Settings.gitlab['twitter_sharing_enabled'],
|
||||
gravatar_enabled: Settings.gravatar['enabled'],
|
||||
sign_in_text: Settings.extra['sign_in_text'],
|
||||
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels']
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ class Issue < ActiveRecord::Base
|
||||
validates :project, presence: true
|
||||
|
||||
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 :cared, ->(user) { where(assignee_id: user) }
|
||||
scope :open_for, ->(user) { opened.assigned_to(user) }
|
||||
|
||||
|
||||
@@ -116,14 +116,14 @@ class ProjectMember < Member
|
||||
def post_create_hook
|
||||
unless owner?
|
||||
event_service.join_project(self.project, self.user)
|
||||
notification_service.new_team_member(self)
|
||||
notification_service.new_project_member(self)
|
||||
end
|
||||
|
||||
system_hook_service.execute_hooks_for(self, :create)
|
||||
end
|
||||
|
||||
def post_update_hook
|
||||
notification_service.update_team_member(self) if self.access_level_changed?
|
||||
notification_service.update_project_member(self) if self.access_level_changed?
|
||||
end
|
||||
|
||||
def post_destroy_hook
|
||||
|
||||
@@ -118,7 +118,6 @@ class MergeRequest < ActiveRecord::Base
|
||||
validate :validate_fork
|
||||
|
||||
scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
|
||||
scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
|
||||
scope :merged, -> { with_state(:merged) }
|
||||
scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) }
|
||||
scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) }
|
||||
|
||||
@@ -137,9 +137,6 @@ class Project < ActiveRecord::Base
|
||||
message: Gitlab::Regex.path_regex_message }
|
||||
validates :issues_enabled, :merge_requests_enabled,
|
||||
: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 :namespace, presence: true
|
||||
validates_uniqueness_of :name, scope: :namespace_id
|
||||
@@ -163,7 +160,6 @@ class Project < ActiveRecord::Base
|
||||
scope :without_user, ->(user) { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) }
|
||||
scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped }
|
||||
scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) }
|
||||
scope :in_team, ->(team) { where('projects.id IN (:ids)', ids: team.projects.map(&:id)) }
|
||||
scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
|
||||
scope :in_group_namespace, -> { joins(:group) }
|
||||
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
|
||||
@@ -459,13 +455,13 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def team_member_by_name_or_email(name = nil, email = nil)
|
||||
def project_member_by_name_or_email(name = nil, email = nil)
|
||||
user = users.where('name like ? or email like ?', name, email).first
|
||||
project_members.where(user: user) if user
|
||||
end
|
||||
|
||||
# Get Team Member record by user id
|
||||
def team_member_by_id(user_id)
|
||||
def project_member_by_id(user_id)
|
||||
project_members.find_by(user_id: user_id)
|
||||
end
|
||||
|
||||
|
||||
@@ -68,9 +68,15 @@ class IrkerService < Service
|
||||
'irker'
|
||||
end
|
||||
|
||||
def execute(push_data)
|
||||
def supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
IrkerWorker.perform_async(project_id, channels,
|
||||
colorize_messages, push_data, @settings)
|
||||
colorize_messages, data, @settings)
|
||||
end
|
||||
|
||||
def fields
|
||||
|
||||
+21
-21
@@ -31,16 +31,16 @@ class ProjectTeam
|
||||
user
|
||||
end
|
||||
|
||||
def find_tm(user_id)
|
||||
tm = project.project_members.find_by(user_id: user_id)
|
||||
def find_member(user_id)
|
||||
member = project.project_members.find_by(user_id: user_id)
|
||||
|
||||
# If user is not in project members
|
||||
# we should check for group membership
|
||||
if group && !tm
|
||||
tm = group.group_members.find_by(user_id: user_id)
|
||||
if group && !member
|
||||
member = group.group_members.find_by(user_id: user_id)
|
||||
end
|
||||
|
||||
tm
|
||||
member
|
||||
end
|
||||
|
||||
def add_user(user, access)
|
||||
@@ -92,24 +92,24 @@ class ProjectTeam
|
||||
def import(source_project)
|
||||
target_project = project
|
||||
|
||||
source_team = source_project.project_members.to_a
|
||||
source_members = source_project.project_members.to_a
|
||||
target_user_ids = target_project.project_members.pluck(:user_id)
|
||||
|
||||
source_team.reject! do |tm|
|
||||
source_members.reject! do |member|
|
||||
# Skip if user already present in team
|
||||
target_user_ids.include?(tm.user_id)
|
||||
target_user_ids.include?(member.user_id)
|
||||
end
|
||||
|
||||
source_team.map! do |tm|
|
||||
new_tm = tm.dup
|
||||
new_tm.id = nil
|
||||
new_tm.source = target_project
|
||||
new_tm
|
||||
source_members.map! do |member|
|
||||
new_member = member.dup
|
||||
new_member.id = nil
|
||||
new_member.source = target_project
|
||||
new_member
|
||||
end
|
||||
|
||||
ProjectMember.transaction do
|
||||
source_team.each do |tm|
|
||||
tm.save
|
||||
source_members.each do |member|
|
||||
member.save
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,26 +119,26 @@ class ProjectTeam
|
||||
end
|
||||
|
||||
def guest?(user)
|
||||
max_tm_access(user.id) == Gitlab::Access::GUEST
|
||||
max_member_access(user.id) == Gitlab::Access::GUEST
|
||||
end
|
||||
|
||||
def reporter?(user)
|
||||
max_tm_access(user.id) == Gitlab::Access::REPORTER
|
||||
max_member_access(user.id) == Gitlab::Access::REPORTER
|
||||
end
|
||||
|
||||
def developer?(user)
|
||||
max_tm_access(user.id) == Gitlab::Access::DEVELOPER
|
||||
max_member_access(user.id) == Gitlab::Access::DEVELOPER
|
||||
end
|
||||
|
||||
def master?(user)
|
||||
max_tm_access(user.id) == Gitlab::Access::MASTER
|
||||
max_member_access(user.id) == Gitlab::Access::MASTER
|
||||
end
|
||||
|
||||
def member?(user_id)
|
||||
!!find_tm(user_id)
|
||||
!!find_member(user_id)
|
||||
end
|
||||
|
||||
def max_tm_access(user_id)
|
||||
def max_member_access(user_id)
|
||||
access = []
|
||||
access << project.project_members.find_by(user_id: user_id).try(:access_field)
|
||||
|
||||
|
||||
@@ -136,8 +136,8 @@ class Repository
|
||||
commit = Gitlab::Git::Commit.new(rugged_commit)
|
||||
|
||||
{
|
||||
author_name: commit.author_name.force_encoding('UTF-8'),
|
||||
author_email: commit.author_email.force_encoding('UTF-8'),
|
||||
author_name: commit.author_name,
|
||||
author_email: commit.author_email,
|
||||
additions: commit.stats.additions,
|
||||
deletions: commit.stats.deletions,
|
||||
}
|
||||
|
||||
+1
-4
@@ -169,13 +169,10 @@ class User < ActiveRecord::Base
|
||||
scope :admins, -> { where(admin: true) }
|
||||
scope :blocked, -> { with_state(:blocked) }
|
||||
scope :active, -> { with_state(:active) }
|
||||
scope :in_team, ->(team){ where(id: team.member_ids) }
|
||||
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
|
||||
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
|
||||
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
|
||||
scope :subscribed_for_admin_email, -> { where(admin_email_unsubscribed_at: nil) }
|
||||
scope :ldap, -> { joins(:identities).where('identities.provider LIKE ?', 'ldap%') }
|
||||
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
|
||||
|
||||
#
|
||||
# Class methods
|
||||
@@ -419,7 +416,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def tm_of(project)
|
||||
project.team_member_by_id(self.id)
|
||||
project.project_member_by_id(self.id)
|
||||
end
|
||||
|
||||
def already_forked?(project)
|
||||
|
||||
@@ -1,9 +1,43 @@
|
||||
class AuditEventService
|
||||
|
||||
def initialize(author, entity, details = {})
|
||||
@author, @entity, @details = author, entity, details
|
||||
end
|
||||
|
||||
def for_member(member)
|
||||
action = @details[:action]
|
||||
old_access_level = @details[:old_access_level]
|
||||
user_id = member.id
|
||||
user_name = member.user.name
|
||||
|
||||
@details =
|
||||
case action
|
||||
when :destroy
|
||||
{
|
||||
remove: "user_access",
|
||||
target_id: user_id,
|
||||
target_type: "User",
|
||||
target_details: user_name,
|
||||
}
|
||||
when :create
|
||||
{
|
||||
add: "user_access",
|
||||
as: Gitlab::Access.options_with_owner.key(member.access_level.to_i),
|
||||
target_id: user_id,
|
||||
target_type: "User",
|
||||
target_details: user_name,
|
||||
}
|
||||
when :update
|
||||
{
|
||||
change: "access_level",
|
||||
from: old_access_level,
|
||||
to: member.human_access,
|
||||
target_id: user_id,
|
||||
target_type: "User",
|
||||
target_details: user_name,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def security_event
|
||||
SecurityEvent.create(
|
||||
author_id: @author.id,
|
||||
|
||||
@@ -31,8 +31,19 @@ class BaseService
|
||||
SystemHooksService.new
|
||||
end
|
||||
|
||||
def current_application_settings
|
||||
ApplicationSetting.current
|
||||
# Add an error to the specified model for restricted visibility levels
|
||||
def deny_visibility_level(model, denied_visibility_level = nil)
|
||||
denied_visibility_level ||= model.visibility_level
|
||||
|
||||
level_name = 'Unknown'
|
||||
Gitlab::VisibilityLevel.options.each do |name, level|
|
||||
level_name = name if level == denied_visibility_level
|
||||
end
|
||||
|
||||
model.errors.add(
|
||||
:visibility_level,
|
||||
"#{level_name} visibility has been restricted by your GitLab administrator"
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -17,10 +17,15 @@ class CreateBranchService < BaseService
|
||||
new_branch = repository.find_branch(branch_name)
|
||||
|
||||
if new_branch
|
||||
EventCreateService.new.push_ref(project, current_user, new_branch, 'add')
|
||||
return success(new_branch)
|
||||
push_data = build_push_data(project, current_user, new_branch)
|
||||
|
||||
EventCreateService.new.push(project, current_user, push_data)
|
||||
project.execute_hooks(push_data.dup, :push_hooks)
|
||||
project.execute_services(push_data.dup, :push_hooks)
|
||||
|
||||
success(new_branch)
|
||||
else
|
||||
return error('Invalid reference name')
|
||||
error('Invalid reference name')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,4 +34,9 @@ class CreateBranchService < BaseService
|
||||
out[:branch] = branch
|
||||
out
|
||||
end
|
||||
|
||||
def build_push_data(project, user, branch)
|
||||
Gitlab::PushDataBuilder.
|
||||
build(project, user, Gitlab::Git::BLANK_SHA, branch.target, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", [])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class CreateSnippetService < BaseService
|
||||
def execute
|
||||
if project.nil?
|
||||
snippet = PersonalSnippet.new(params)
|
||||
else
|
||||
snippet = project.snippets.build(params)
|
||||
end
|
||||
|
||||
unless Gitlab::VisibilityLevel.allowed_for?(current_user,
|
||||
params[:visibility_level])
|
||||
deny_visibility_level(snippet)
|
||||
return snippet
|
||||
end
|
||||
|
||||
snippet.author = current_user
|
||||
|
||||
snippet.save
|
||||
snippet
|
||||
end
|
||||
end
|
||||
@@ -21,9 +21,9 @@ class CreateTagService < BaseService
|
||||
new_tag = repository.find_tag(tag_name)
|
||||
|
||||
if new_tag
|
||||
EventCreateService.new.push_ref(project, current_user, new_tag, 'add', Gitlab::Git::TAG_REF_PREFIX)
|
||||
|
||||
push_data = create_push_data(project, current_user, new_tag)
|
||||
|
||||
EventCreateService.new.push(project, current_user, push_data)
|
||||
project.execute_hooks(push_data.dup, :tag_push_hooks)
|
||||
project.execute_services(push_data.dup, :tag_push_hooks)
|
||||
|
||||
@@ -40,9 +40,7 @@ class CreateTagService < BaseService
|
||||
end
|
||||
|
||||
def create_push_data(project, user, tag)
|
||||
data = Gitlab::PushDataBuilder.
|
||||
Gitlab::PushDataBuilder.
|
||||
build(project, user, Gitlab::Git::BLANK_SHA, tag.target, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", [])
|
||||
data[:object_kind] = "tag_push"
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,10 +25,15 @@ class DeleteBranchService < BaseService
|
||||
end
|
||||
|
||||
if repository.rm_branch(branch_name)
|
||||
EventCreateService.new.push_ref(project, current_user, branch, 'rm')
|
||||
push_data = build_push_data(branch)
|
||||
|
||||
EventCreateService.new.push(project, current_user, push_data)
|
||||
project.execute_hooks(push_data.dup, :push_hooks)
|
||||
project.execute_services(push_data.dup, :push_hooks)
|
||||
|
||||
success('Branch was removed')
|
||||
else
|
||||
return error('Failed to remove branch')
|
||||
error('Failed to remove branch')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,4 +48,9 @@ class DeleteBranchService < BaseService
|
||||
out[:message] = message
|
||||
out
|
||||
end
|
||||
|
||||
def build_push_data(branch)
|
||||
Gitlab::PushDataBuilder
|
||||
.build(project, current_user, branch.target, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", [])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
require_relative 'base_service'
|
||||
|
||||
class DeleteTagService < BaseService
|
||||
def execute(tag_name)
|
||||
repository = project.repository
|
||||
tag = repository.find_tag(tag_name)
|
||||
|
||||
# No such tag
|
||||
unless tag
|
||||
return error('No such tag', 404)
|
||||
end
|
||||
|
||||
if repository.rm_tag(tag_name)
|
||||
push_data = build_push_data(tag)
|
||||
|
||||
EventCreateService.new.push(project, current_user, push_data)
|
||||
project.execute_hooks(push_data.dup, :tag_push_hooks)
|
||||
project.execute_services(push_data.dup, :tag_push_hooks)
|
||||
|
||||
success('Tag was removed')
|
||||
else
|
||||
error('Failed to remove tag')
|
||||
end
|
||||
end
|
||||
|
||||
def error(message, return_code = 400)
|
||||
out = super(message)
|
||||
out[:return_code] = return_code
|
||||
out
|
||||
end
|
||||
|
||||
def success(message)
|
||||
out = super()
|
||||
out[:message] = message
|
||||
out
|
||||
end
|
||||
|
||||
def build_push_data(tag)
|
||||
Gitlab::PushDataBuilder
|
||||
.build(project, current_user, tag.target, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", [])
|
||||
end
|
||||
end
|
||||
@@ -62,26 +62,6 @@ class EventCreateService
|
||||
create_event(project, current_user, Event::CREATED)
|
||||
end
|
||||
|
||||
def push_ref(project, current_user, ref, action = 'add', prefix = Gitlab::Git::BRANCH_REF_PREFIX)
|
||||
commit = project.repository.commit(ref.target)
|
||||
|
||||
if action.to_s == 'add'
|
||||
before = Gitlab::Git::BLANK_SHA
|
||||
after = commit.id
|
||||
else
|
||||
before = commit.id
|
||||
after = Gitlab::Git::BLANK_SHA
|
||||
end
|
||||
|
||||
data = {
|
||||
ref: "#{prefix}#{ref.name}",
|
||||
before: before,
|
||||
after: after
|
||||
}
|
||||
|
||||
push(project, current_user, data)
|
||||
end
|
||||
|
||||
def push(project, current_user, push_data)
|
||||
create_event(project, current_user, Event::PUSHED, data: push_data)
|
||||
end
|
||||
|
||||
@@ -53,7 +53,8 @@ class GitPushService
|
||||
process_commit_messages(ref)
|
||||
end
|
||||
|
||||
@push_data = post_receive_data(oldrev, newrev, ref)
|
||||
@push_data = build_push_data(oldrev, newrev, ref)
|
||||
|
||||
EventCreateService.new.push(project, user, @push_data)
|
||||
project.execute_hooks(@push_data.dup, :push_hooks)
|
||||
project.execute_services(@push_data.dup, :push_hooks)
|
||||
@@ -105,7 +106,7 @@ class GitPushService
|
||||
end
|
||||
end
|
||||
|
||||
def post_receive_data(oldrev, newrev, ref)
|
||||
def build_push_data(oldrev, newrev, ref)
|
||||
Gitlab::PushDataBuilder.
|
||||
build(project, user, oldrev, newrev, ref, push_commits)
|
||||
end
|
||||
|
||||
@@ -3,21 +3,21 @@ class GitTagPushService
|
||||
|
||||
def execute(project, user, oldrev, newrev, ref)
|
||||
@project, @user = project, user
|
||||
@push_data = create_push_data(oldrev, newrev, ref)
|
||||
|
||||
@push_data = build_push_data(oldrev, newrev, ref)
|
||||
|
||||
EventCreateService.new.push(project, user, @push_data)
|
||||
project.repository.expire_cache
|
||||
project.execute_hooks(@push_data.dup, :tag_push_hooks)
|
||||
project.execute_services(@push_data.dup, :tag_push_hooks)
|
||||
|
||||
project.repository.expire_cache
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_push_data(oldrev, newrev, ref)
|
||||
data = Gitlab::PushDataBuilder.build(project, user, oldrev, newrev, ref, [])
|
||||
data[:object_kind] = "tag_push"
|
||||
data
|
||||
def build_push_data(oldrev, newrev, ref)
|
||||
Gitlab::PushDataBuilder.build(project, user, oldrev, newrev, ref, [])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -162,20 +162,20 @@ class NotificationService
|
||||
end
|
||||
end
|
||||
|
||||
def new_team_member(project_member)
|
||||
def new_project_member(project_member)
|
||||
mailer.project_access_granted_email(project_member.id)
|
||||
end
|
||||
|
||||
def update_team_member(project_member)
|
||||
def update_project_member(project_member)
|
||||
mailer.project_access_granted_email(project_member.id)
|
||||
end
|
||||
|
||||
def new_group_member(users_group)
|
||||
mailer.group_access_granted_email(users_group.id)
|
||||
def new_group_member(group_member)
|
||||
mailer.group_access_granted_email(group_member.id)
|
||||
end
|
||||
|
||||
def update_group_member(users_group)
|
||||
mailer.group_access_granted_email(users_group.id)
|
||||
def update_group_member(group_member)
|
||||
mailer.group_access_granted_email(group_member.id)
|
||||
end
|
||||
|
||||
def project_was_moved(project)
|
||||
@@ -194,11 +194,11 @@ class NotificationService
|
||||
project_members = project_member_notification(project)
|
||||
|
||||
users_with_project_level_global = project_member_notification(project, Notification::N_GLOBAL)
|
||||
users_with_group_level_global = users_group_notification(project, Notification::N_GLOBAL)
|
||||
users_with_group_level_global = group_member_notification(project, Notification::N_GLOBAL)
|
||||
users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq)
|
||||
|
||||
users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users)
|
||||
users_with_group_setting = select_users_group_setting(project, project_members, users_with_group_level_global, users)
|
||||
users_with_group_setting = select_group_member_setting(project, project_members, users_with_group_level_global, users)
|
||||
|
||||
User.where(id: users_with_project_setting.concat(users_with_group_setting).uniq).to_a
|
||||
end
|
||||
@@ -213,7 +213,7 @@ class NotificationService
|
||||
end
|
||||
end
|
||||
|
||||
def users_group_notification(project, notification_level)
|
||||
def group_member_notification(project, notification_level)
|
||||
if project.group
|
||||
project.group.group_members.where(notification_level: notification_level).pluck(:user_id)
|
||||
else
|
||||
@@ -243,8 +243,8 @@ class NotificationService
|
||||
end
|
||||
|
||||
# Build a list of users based on group notification settings
|
||||
def select_users_group_setting(project, project_members, global_setting, users_global_level_watch)
|
||||
uids = users_group_notification(project, Notification::N_WATCH)
|
||||
def select_group_member_setting(project, project_members, global_setting, users_global_level_watch)
|
||||
uids = group_member_notification(project, Notification::N_WATCH)
|
||||
|
||||
# Group setting is watch, add to users list if user is not project member
|
||||
users = []
|
||||
@@ -273,20 +273,20 @@ class NotificationService
|
||||
users.reject do |user|
|
||||
next user.notification.disabled? unless project
|
||||
|
||||
tm = project.project_members.find_by(user_id: user.id)
|
||||
member = project.project_members.find_by(user_id: user.id)
|
||||
|
||||
if !tm && project.group
|
||||
tm = project.group.group_members.find_by(user_id: user.id)
|
||||
if !member && project.group
|
||||
member = project.group.group_members.find_by(user_id: user.id)
|
||||
end
|
||||
|
||||
# reject users who globally disabled notification and has no membership
|
||||
next user.notification.disabled? unless tm
|
||||
next user.notification.disabled? unless member
|
||||
|
||||
# reject users who disabled notification in project
|
||||
next true if tm.notification.disabled?
|
||||
next true if member.notification.disabled?
|
||||
|
||||
# reject users who have N_GLOBAL in project and disabled in global settings
|
||||
tm.notification.global? && user.notification.disabled?
|
||||
member.notification.global? && user.notification.disabled?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -297,20 +297,20 @@ class NotificationService
|
||||
users.reject do |user|
|
||||
next user.notification.mention? unless project
|
||||
|
||||
tm = project.project_members.find_by(user_id: user.id)
|
||||
member = project.project_members.find_by(user_id: user.id)
|
||||
|
||||
if !tm && project.group
|
||||
tm = project.group.group_members.find_by(user_id: user.id)
|
||||
if !member && project.group
|
||||
member = project.group.group_members.find_by(user_id: user.id)
|
||||
end
|
||||
|
||||
# reject users who globally set mention notification and has no membership
|
||||
next user.notification.mention? unless tm
|
||||
next user.notification.mention? unless member
|
||||
|
||||
# reject users who set mention notification in project
|
||||
next true if tm.notification.mention?
|
||||
next true if member.notification.mention?
|
||||
|
||||
# reject users who have N_MENTION in project and disabled in global settings
|
||||
tm.notification.global? && user.notification.mention?
|
||||
member.notification.global? && user.notification.mention?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -7,9 +7,12 @@ module Projects
|
||||
def execute
|
||||
@project = Project.new(params)
|
||||
|
||||
# Reset visibility level if is not allowed to set it
|
||||
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
|
||||
@project.visibility_level = default_features.visibility_level
|
||||
# Make sure that the user is allowed to use the specified visibility
|
||||
# level
|
||||
unless Gitlab::VisibilityLevel.allowed_for?(current_user,
|
||||
params[:visibility_level])
|
||||
deny_visibility_level(@project)
|
||||
return @project
|
||||
end
|
||||
|
||||
# Set project name from path
|
||||
|
||||
@@ -12,8 +12,8 @@ module Projects
|
||||
else
|
||||
[]
|
||||
end
|
||||
team_members = sorted(@project.team.members)
|
||||
participants = all_members + groups + team_members + participating
|
||||
project_members = sorted(@project.team.members)
|
||||
participants = all_members + groups + project_members + participating
|
||||
participants.uniq
|
||||
end
|
||||
|
||||
|
||||
@@ -2,8 +2,13 @@ module Projects
|
||||
class UpdateService < BaseService
|
||||
def execute
|
||||
# check that user is allowed to set specified visibility_level
|
||||
unless can?(current_user, :change_visibility_level, project) && Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
|
||||
params[:visibility_level] = project.visibility_level
|
||||
new_visibility = params[:visibility_level]
|
||||
if new_visibility && new_visibility.to_i != project.visibility_level
|
||||
unless can?(current_user, :change_visibility_level, project) &&
|
||||
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
|
||||
deny_visibility_level(project, new_visibility)
|
||||
return project
|
||||
end
|
||||
end
|
||||
|
||||
new_branch = params[:default_branch]
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
class UpdateSnippetService < BaseService
|
||||
attr_accessor :snippet
|
||||
|
||||
def initialize(project, user, snippet, params)
|
||||
super(project, user, params)
|
||||
@snippet = snippet
|
||||
end
|
||||
|
||||
def execute
|
||||
# check that user is allowed to set specified visibility_level
|
||||
new_visibility = params[:visibility_level]
|
||||
if new_visibility && new_visibility.to_i != snippet.visibility_level
|
||||
unless can?(current_user, :change_visibility_level, snippet) &&
|
||||
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
|
||||
deny_visibility_level(snippet, new_visibility)
|
||||
return snippet
|
||||
end
|
||||
end
|
||||
|
||||
snippet.update_attributes(params)
|
||||
end
|
||||
end
|
||||
@@ -42,6 +42,14 @@
|
||||
= 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
|
||||
= f.label :restricted_visibility_levels, class: 'control-label col-sm-2'
|
||||
.col-sm-10
|
||||
- data_attrs = { toggle: 'buttons' }
|
||||
.btn-group{ data: data_attrs }
|
||||
- restricted_level_checkboxes('restricted-visibility-help').each do |level|
|
||||
= level
|
||||
%span.help-block#restricted-visibility-help Selected levels cannot be used by non-admin users for projects or snippets
|
||||
.form-group
|
||||
= f.label :home_page_url, class: 'control-label col-sm-2'
|
||||
.col-sm-10
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- submit_btn_css ||= 'btn btn-link btn-remove btn-small'
|
||||
- submit_btn_css ||= 'btn btn-link btn-remove btn-sm'
|
||||
= form_tag admin_application_path(application) do
|
||||
%input{:name => "_method", :type => "hidden", :value => "delete"}/
|
||||
= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
|
||||
@@ -52,7 +52,7 @@
|
||||
%strong
|
||||
#{broadcast_message.ends_at.to_s(:short)}
|
||||
|
||||
= link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-tiny' do
|
||||
= link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-xs' do
|
||||
%i.fa.fa-times.cred
|
||||
|
||||
.message= broadcast_message.message
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
%li
|
||||
.clearfix
|
||||
.pull-right.prepend-top-10
|
||||
= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-small"
|
||||
= link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: "btn btn-small btn-remove"
|
||||
= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn btn-sm"
|
||||
= link_to 'Destroy', [:admin, group], data: {confirm: "REMOVE #{group.name}? Are you sure?"}, method: :delete, class: "btn btn-sm btn-remove"
|
||||
|
||||
%h4
|
||||
= link_to [:admin, group] do
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
Group info:
|
||||
%ul.well-list
|
||||
%li
|
||||
= image_tag group_icon(@group.path), class: "avatar s60"
|
||||
= image_tag group_icon(@group), class: "avatar s60"
|
||||
%li
|
||||
%span.light Name:
|
||||
%strong= @group.name
|
||||
@@ -85,7 +85,7 @@
|
||||
Read more about project permissions
|
||||
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
|
||||
|
||||
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
|
||||
= form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
|
||||
%div
|
||||
= users_select_tag(:user_ids, { multiple: true, skip_ldap: @group.ldap_synced? })
|
||||
%div.prepend-top-10
|
||||
@@ -107,7 +107,7 @@
|
||||
= link_to user.name, admin_user_path(user)
|
||||
%span.pull-right.light
|
||||
= member.human_access
|
||||
= link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
= link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do
|
||||
%i.fa.fa-minus.fa-inverse
|
||||
.panel-footer
|
||||
= paginate @members, param_name: 'members_page', theme: 'gitlab'
|
||||
|
||||
@@ -33,5 +33,5 @@
|
||||
%strong= hook.url
|
||||
|
||||
.pull-right
|
||||
= link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-small"
|
||||
= link_to 'Remove', admin_hook_path(hook), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-remove btn-small"
|
||||
= link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-sm"
|
||||
= link_to 'Remove', admin_hook_path(hook), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-remove btn-sm"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user