Commit 7c1acb02 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Merge remote-tracking branch 'origin/master' into with-pipeline-view

# Conflicts:
#	app/views/projects/ci/builds/_build.html.haml
#	app/views/projects/commit/_ci_commit.html.haml
#	app/views/projects/commit/_commit_box.html.haml
parents 1ad0c968 44501820
......@@ -953,10 +953,9 @@ Performance/DoubleStartEndWith:
Performance/EndWith:
Enabled: false
# TODO: Enable LstripRstrip Cop.
# Use `strip` instead of `lstrip.rstrip`.
Performance/LstripRstrip:
Enabled: false
Enabled: true
# TODO: Enable RangeInclude Cop.
# Use `Range#cover?` instead of `Range#include?`.
......
......@@ -244,11 +244,11 @@ linters:
# URLs should be valid and not contain protocols or domain names.
UrlFormat:
enabled: false
enabled: true
# URLs should always be enclosed within quotes.
UrlQuotes:
enabled: false
enabled: true
# Properties, like color and font, are easier to read and maintain
# when defined using variables rather than literals.
......
Please view this file on the master branch, on stable branches it's out of date.
v 8.8.0 (unreleased)
- Assign labels and milestone to target project when moving issue. !3934 (Long Nguyen)
- Project#open_branches has been cleaned up and no longer loads entire records into memory.
- Log to application.log when an admin starts and stops impersonating a user
- Updated gitlab_git to 10.1.0
- GitAccess#protected_tag? no longer loads all tags just to check if a single one exists
- Reduce delay in destroying a project from 1-minute to immediately
- Make build status canceled if any of the jobs was canceled and none failed
- Upgrade Sidekiq to 4.1.2
- Sanitize repo paths in new project error message
- Bump mail_room to 0.7.0 to fix stuck IDLE connections
- Remove future dates from contribution calendar graph.
- Support e-mail notifications for comments on project snippets
- Use ActionDispatch Remote IP for Akismet checking
- Fix error when visiting commit builds page before build was updated
- Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project
v 8.7.1 (unreleased)
- Update SVG sanitizer to conform to SVG 1.1
- Updated search UI
- Display informative message when new milestone is created
- Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea)
- Added button to toggle whitespaces changes on diff view
- Backport GitHub Enterprise import support from EE
- Create tags using Rugged for performance reasons. !3745
- Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718
- Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes)
- Added multiple colors for labels in dropdowns when dups happen.
- Improve description for the Two-factor Authentication sign-in screen. (Connor Shea)
- API support for the 'since' and 'until' operators on commit requests (Paco Guzman)
- Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko)
- Expire repository exists? and has_visible_content? caches after a push if necessary
- Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi)
v 8.7.3
- Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
- Merge request widget displays TeamCity build state and code coverage correctly again.
- Fix the line code when importing PR review comments from GitHub. !4010
- Wikis are now initialized on legacy projects when checking repositories
v 8.7.2
- The "New Branch" button is now loaded asynchronously
- Fix error 500 when trying to create a wiki page
- Updated spacing between notification label and button
- Label titles in filters are now escaped properly
v 8.7.1
- Throttle the update of `project.last_activity_at` to 1 minute. !3848
- Fix .gitlab-ci.yml parsing issue when hidde job is a template without script definition. !3849
- Fix license detection to detect all license files, not only known licenses. !3878
- Use the `can?` helper instead of `current_user.can?`. !3882
- Prevent users from deleting Webhooks via API they do not own
- Fix Error 500 due to stale cache when projects are renamed or transferred
- Update width of search box to fix Safari bug. !3900 (Jedidiah)
- Use the `can?` helper instead of `current_user.can?`
v 8.7.0
- Gitlab::GitAccess and Gitlab::GitAccessWiki are now instrumented
......@@ -123,13 +164,25 @@ v 8.7.0
- Import GitHub labels
- Add option to filter by "Owned projects" on dashboard page
- Import GitHub milestones
- Fix emoji catgories in the emoji picker
- Execute system web hooks on push to the project
- Allow enable/disable push events for system hooks
- Fix GitHub project's link in the import page when provider has a custom URL
- Add RAW build trace output and button on build page
- Add incremental build trace update into CI API
v 8.6.8
- Prevent privilege escalation via "impersonate" feature
- Prevent privilege escalation via notes API
- Prevent privilege escalation via project webhook API
- Prevent XSS via Git branch and tag names
- Prevent XSS via custom issue tracker URL
- Prevent XSS via `window.opener`
- Prevent XSS via label drop-down
- Prevent information disclosure via milestone API
- Prevent information disclosure via snippet API
- Prevent information disclosure via project labels
- Prevent information disclosure via new merge request page
v 8.6.7
- Fix persistent XSS vulnerability in `commit_person_link` helper
- Fix persistent XSS vulnerability in Label and Milestone dropdowns
......@@ -271,6 +324,17 @@ v 8.6.0
- Trigger a todo for mentions on commits page
- Let project owners and admins soft delete issues and merge requests
v 8.5.12
- Prevent privilege escalation via "impersonate" feature
- Prevent privilege escalation via notes API
- Prevent privilege escalation via project webhook API
- Prevent XSS via Git branch and tag names
- Prevent XSS via custom issue tracker URL
- Prevent XSS via `window.opener`
- Prevent information disclosure via snippet API
- Prevent information disclosure via project labels
- Prevent information disclosure via new merge request page
v 8.5.11
- Fix persistent XSS vulnerability in `commit_person_link` helper
......@@ -421,6 +485,17 @@ v 8.5.0
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Add Todos
v 8.4.10
- Prevent privilege escalation via "impersonate" feature
- Prevent privilege escalation via notes API
- Prevent privilege escalation via project webhook API
- Prevent XSS via Git branch and tag names
- Prevent XSS via custom issue tracker URL
- Prevent XSS via `window.opener`
- Prevent information disclosure via snippet API
- Prevent information disclosure via project labels
- Prevent information disclosure via new merge request page
v 8.4.9
- Fix persistent XSS vulnerability in `commit_person_link` helper
......@@ -546,6 +621,15 @@ v 8.4.0
- Add IP check against DNSBLs at account sign-up
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
v 8.3.9
- Prevent privilege escalation via "impersonate" feature
- Prevent privilege escalation via notes API
- Prevent privilege escalation via project webhook API
- Prevent XSS via custom issue tracker URL
- Prevent XSS via `window.opener`
- Prevent information disclosure via project labels
- Prevent information disclosure via new merge request page
v 8.3.8
- Fix persistent XSS vulnerability in `commit_person_link` helper
......@@ -655,6 +739,17 @@ v 8.3.0
- Expose Git's version in the admin area
- Show "New Merge Request" buttons on canonical repos when you have a fork (Josh Frye)
v 8.2.5
- Prevent privilege escalation via "impersonate" feature
- Prevent privilege escalation via notes API
- Prevent privilege escalation via project webhook API
- Prevent XSS via `window.opener`
- Prevent information disclosure via project labels
- Prevent information disclosure via new merge request page
v 8.2.4
- Bump Git version requirement to 2.7.4
v 8.2.3
- Fix application settings cache not expiring after changes (Stan Hu)
- Fix Error 500s when creating global milestones with Unicode characters (Stan Hu)
......
......@@ -38,7 +38,7 @@ source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
If you have read this guide and want to know how the GitLab [core team][core-team]
If you have read this guide and want to know how the GitLab [core team]
operates please see [the GitLab contributing process](PROCESS.md).
## Contributor license agreement
......@@ -135,12 +135,23 @@ For feature proposals for EE, open an issue on the
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team][core-team]
members to add the label `feature proposal` to the issue.
of the project cannot add labels. You can instead ask one of the [core team]
members to add the label `feature proposal` to the issue or add the following
code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
You are encouraged to use the template below for feature proposals.
```
## Description including problem, use cases, benefits, and/or goals
## Proposal
## Links / references
```
For changes in the interface, it can be helpful to create a mockup first.
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
......@@ -344,12 +355,11 @@ is it will be merged (quickly). After that you can send more MRs to enhance it.
For examples of feedback on merge requests please look at already
[closed merge requests][closed-merge-requests]. If you would like quick feedback
on your merge request feel free to mention one of the Merge Marshalls in the
[core team][core-team] or one of the
[Merge request coaches](https://about.gitlab.com/team/).
[core team] or one of the [Merge request coaches](https://about.gitlab.com/team/).
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
[Thoughtbot code review guide] into account.
[code review guidelines](doc/development/code_review.md) into account.
### Merge request description format
......@@ -497,7 +507,7 @@ reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
[core-team]: https://about.gitlab.com/core-team/
[core team]: https://about.gitlab.com/core-team/
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
......@@ -523,4 +533,3 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
[`gitlab1.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/gitlab1.atype/
[Thoughtbot code review guide]: https://github.com/thoughtbot/guides/tree/master/code-review
......@@ -19,8 +19,8 @@ gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.4'
gem 'doorkeeper', '~> 3.1'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.3.1'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
......@@ -243,7 +243,7 @@ group :development do
gem 'brakeman', '~> 3.2.0', require: false
gem "annotate", "~> 2.7.0"
gem "letter_opener", '~> 1.1.2'
gem 'letter_opener_web', '~> 1.3.0'
gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.11.0'
gem 'bullet', require: false
......@@ -270,7 +270,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.3.0'
gem 'rspec-rails', '~> 3.4.0'
gem 'rspec-retry'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
......@@ -320,7 +320,7 @@ gem "newrelic_rpm", '~> 3.14'
gem 'octokit', '~> 4.3.0'
gem "mail_room", "~> 0.6.1"
gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8'
......
......@@ -134,7 +134,7 @@ GEM
execjs
coffee-script-source (1.10.0)
colorize (0.7.7)
concurrent-ruby (1.0.1)
concurrent-ruby (1.0.2)
connection_pool (2.2.0)
coveralls (0.8.13)
json (~> 1.8)
......@@ -175,7 +175,7 @@ GEM
diff-lcs (1.2.5)
diffy (3.0.7)
docile (1.1.5)
doorkeeper (2.2.2)
doorkeeper (3.1.0)
railties (>= 3.2)
dropzonejs-rails (0.7.2)
rails (> 3.1)
......@@ -186,7 +186,7 @@ GEM
encryptor (1.3.0)
equalizer (0.0.11)
erubis (2.7.0)
escape_utils (1.1.0)
escape_utils (1.1.1)
eventmachine (1.0.8)
excon (0.45.4)
execjs (2.6.0)
......@@ -336,7 +336,7 @@ GEM
json
get_process_mem (0.2.0)
gherkin-ruby (0.3.2)
github-linguist (4.7.5)
github-linguist (4.7.6)
charlock_holmes (~> 0.7.3)
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
......@@ -353,7 +353,7 @@ GEM
posix-spawn (~> 0.3)
gitlab_emoji (0.3.1)
gemojione (~> 2.2, >= 2.2.1)
gitlab_git (10.0.0)
gitlab_git (10.1.0)
activesupport (~> 4.0)
charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0)
......@@ -450,8 +450,12 @@ GEM
kgio (2.10.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.1.2)
letter_opener (1.4.1)
launchy (~> 2.2)
letter_opener_web (1.3.0)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
licensee (8.0.0)
rugged (>= 0.24b)
listen (3.0.5)
......@@ -463,7 +467,7 @@ GEM
systemu (~> 2.6.2)
mail (2.6.4)
mime-types (>= 1.16, < 4)
mail_room (0.6.1)
mail_room (0.7.0)
method_source (0.8.2)
mime-types (2.99.1)
mimemagic (0.3.0)
......@@ -660,29 +664,29 @@ GEM
chunky_png
rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2)
rspec (3.3.0)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0)
rspec-core (3.3.2)
rspec-support (~> 3.3.0)
rspec-expectations (3.3.1)
rspec (3.4.0)
rspec-core (~> 3.4.0)
rspec-expectations (~> 3.4.0)
rspec-mocks (~> 3.4.0)
rspec-core (3.4.4)
rspec-support (~> 3.4.0)
rspec-expectations (3.4.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-mocks (3.3.2)
rspec-support (~> 3.4.0)
rspec-mocks (3.4.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.3.0)
rspec-rails (3.3.3)
rspec-support (~> 3.4.0)
rspec-rails (3.4.2)
actionpack (>= 3.0, < 4.3)
activesupport (>= 3.0, < 4.3)
railties (>= 3.0, < 4.3)
rspec-core (~> 3.3.0)
rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0)
rspec-support (~> 3.3.0)
rspec-core (~> 3.4.0)
rspec-expectations (~> 3.4.0)
rspec-mocks (~> 3.4.0)
rspec-support (~> 3.4.0)
rspec-retry (0.4.5)
rspec-core
rspec-support (3.3.0)
rspec-support (3.4.1)
rubocop (0.38.0)
parser (>= 2.3.0.6, < 3.0)
powerpack (~> 0.1)
......@@ -736,7 +740,7 @@ GEM
rack
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
sidekiq (4.1.1)
sidekiq (4.1.2)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
redis (~> 3.2, >= 3.2.1)
......@@ -921,7 +925,7 @@ DEPENDENCIES
devise-async (~> 0.9.0)
devise-two-factor (~> 2.0.0)
diffy (~> 3.0.3)
doorkeeper (~> 2.2.0)
doorkeeper (~> 3.1)
dropzonejs-rails (~> 0.7.1)
email_reply_parser (~> 0.5.8)
email_spec (~> 1.6.0)
......@@ -957,10 +961,10 @@ DEPENDENCIES
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0)
kaminari (~> 0.16.3)
letter_opener (~> 1.1.2)
letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0)
loofah (~> 2.0.3)
mail_room (~> 0.6.1)
mail_room (~> 0.7)
method_source (~> 0.8)
minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6)
......@@ -1010,7 +1014,7 @@ DEPENDENCIES
responders (~> 2.0)
rouge (~> 1.10.1)
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0)
rspec-rails (~> 3.4.0)
rspec-retry
rubocop (~> 0.38.0)
ruby-fogbugz (~> 0.2.1)
......@@ -1057,4 +1061,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
1.11.2
1.12.1
......@@ -59,7 +59,7 @@ core team members will mention this person.
Workflow labels are purposely not very detailed since that would be hard to keep
updated as you would need to re-evaluate them after every comment. We optionally
use functional labels on demand when want to group related issues to get an
use functional labels on demand when we want to group related issues to get an
overview (for example all issues related to RVM, to tackle them in one go) and
to add details to the issue.
......@@ -73,6 +73,7 @@ in support or comment for further detail. Do not use `feature request`.
- ~bug is an issue reporting undesirable or incorrect behavior.
- ~customer is an issue reported by enterprise subscribers. This label should
be accompanied by *bug* or *feature proposal* labels.
Example workflow: when a UX designer provided a design but it needs frontend work they remove the UX label and add the frontend label.
## Functional labels
......
# GitLab
[![build status](https://ci.gitlab.com/projects/1/status.svg?ref=master)](https://ci.gitlab.com/projects/1?ref=master)
[![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.svg?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
......@@ -20,6 +20,10 @@ To see how GitLab looks please see the [features page on our website](https://ab
- Completely free and open source (MIT Expat license)
- Powered by [Ruby on Rails](https://github.com/rails/rails)
## Hiring
We're hiring developers, support people, and production engineers all the time, please see our [jobs page](https://about.gitlab.com/jobs/).
## Editions
There are two editions of GitLab:
......@@ -80,7 +84,7 @@ There are a lot of [third-party applications integrating with GitLab](https://ab
## GitLab release cycle
For more information about the release process see the [release documentation](http://doc.gitlab.com/ce/release/).
For more information about the release process see the [release documentation](https://gitlab.com/gitlab-org/release-tools/blob/master/README.md).
## Upgrading
......
......@@ -108,6 +108,8 @@ class Dispatcher
new BuildArtifacts()
when 'projects:group_links:index'
new GroupsSelect()
when 'search:show'
new Search()
switch path.first()
when 'admin'
......
......@@ -184,6 +184,9 @@ class GitLabDropdown
@dropdown.on "shown.bs.dropdown", @opened
@dropdown.on "hidden.bs.dropdown", @hidden
@dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate
@dropdown.on 'keyup', (e) =>
if e.which is 27 # Escape key
$('.dropdown-menu-close', @dropdown).trigger 'click'
if @dropdown.find(".dropdown-toggle-page").length
@dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) =>
......
......@@ -12,6 +12,7 @@ class @Issue
@initMergeRequests()
@initRelatedBranches()
@initCanCreateBranch()
initTaskList: ->
$('.detail-page-description .js-task-list-container').taskList('enable')
......@@ -92,3 +93,25 @@ class @Issue
.success (data) ->
if 'html' of data
$container.html(data.html)
initCanCreateBranch: ->
$container = $('div#new-branch')
# If the user doesn't have the required permissions the container isn't
# rendered at all.
return unless $container
$.getJSON($container.data('path'))
.error ->
$container.find('.checking').hide()
$container.find('.unavailable').show()
new Flash('Failed to check if a new branch can be created.', 'alert')
.success (data) ->
if data.can_create_branch
$container.find('.checking').hide()
$container.find('.available').show()
$container.find('a').attr('disabled', false)
else
$container.find('.checking').hide()
$container.find('.unavailable').show()
......@@ -30,7 +30,7 @@ class @LabelsSelect
if issueUpdateURL
labelHTMLTemplate = _.template(
'<% _.each(labels, function(label){ %>
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= _.escape(label.title) %>">
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%= _.escape(label.title) %>">
<span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>; color: <%= label.text_color %>;">
<%= _.escape(label.title) %>
</span>
......@@ -163,6 +163,21 @@ class @LabelsSelect
$.ajax(
url: labelUrl
).done (data) ->
data = _.chain data
.groupBy (label) ->
label.title
.map (label) ->
color = _.map label, (dup) ->
dup.color
return {
id: label[0].id
title: label[0].title
color: color
duplicate: color.length > 1
}
.value()
if $dropdown.hasClass 'js-extra-options'
if showNo
data.unshift(
......@@ -178,6 +193,7 @@ class @LabelsSelect
if data.length > 2
data.splice 2, 0, 'divider'
callback data
renderRow: (label) ->
......@@ -192,11 +208,31 @@ class @LabelsSelect
if $dropdown.hasClass('js-multiselect') and removesAll
selectedClass.push 'dropdown-clear-active'
color = if label.color? then "<span class='dropdown-label-box' style='background-color: #{label.color}'></span>" else ""
if label.duplicate
spacing = 100 / label.color.length
# Reduce the colors to 4
label.color = label.color.filter (color, i) ->
i < 4
color = _.map(label.color, (color, i) ->
percentFirst = Math.floor(spacing * i)
percentSecond = Math.floor(spacing * (i + 1))
"#{color} #{percentFirst}%,#{color} #{percentSecond}% "
).join(',')
color = "linear-gradient(#{color})"
else
if label.color?
color = label.color[0]
if color
colorEl = "<span class='dropdown-label-box' style='background: #{color}'></span>"
else
colorEl = ''
"<li>
<a href='#' class='#{selectedClass.join(' ')}'>
#{color}
#{colorEl}
#{_.escape(label.title)}
</a>
</li>"
......
......@@ -68,20 +68,18 @@ class @MergeRequestWidget
$.getJSON @opts.ci_status_url, (data) =>
@readyForCICheck = true
if @firstCICheck
@firstCICheck = false
@opts.ci_status = data.status
if @opts.ci_status is ''
@opts.ci_status = data.status
if data.status is ''
return
if data.status isnt @opts.ci_status and data.status?
if @firstCiCheck || data.status isnt @opts.ci_status and data.status?
@opts.ci_status = data.status
@showCIStatus data.status
if data.coverage
@showCICoverage data.coverage
if showNotification
# The first check should only update the UI, a notification
# should only be displayed on status changes
if showNotification and not @firstCiCheck
status = @ciLabelForStatus(data.status)
if status is "preparing"
......@@ -104,8 +102,7 @@ class @MergeRequestWidget
@close()
Turbolinks.visit _this.opts.builds_path
)
@opts.ci_status = data.status
@firstCiCheck = false
showCIStatus: (state) ->
$('.ci_widget').hide()
......
......@@ -167,8 +167,8 @@ class @Notes
return
if note.award
awards_handler.addAwardToEmojiBar(note.note)
awards_handler.scrollToAwards()
awardsHandler.addAwardToEmojiBar(note.note)
awardsHandler.scrollToAwards()
# render note if it not present in loaded list
# or skip if rendered
......@@ -373,11 +373,11 @@ class @Notes
new GLForm form
if scrollTo? and myLastNote?
# scroll to the bottom
# scroll to the bottom
# so the open of the last element doesn't make a jump
$('html, body').scrollTop($(document).height());
$('html, body').animate({
scrollTop: myLastNote.offset().top - 150
scrollTop: myLastNote.offset().top - 150
}, 500, ->
$noteText = form.find(".js-note-text")
$noteText.focus()
......
class @Search
constructor: ->
$groupDropdown = $('.js-search-group-dropdown')
$projectDropdown = $('.js-search-project-dropdown')
@eventListeners()
$groupDropdown.glDropdown(
selectable: true
filterable: true
fieldName: 'group_id'
data: (term, callback) ->
Api.groups term, null, (data) ->
data.unshift(
name: 'Any'
)
data.splice 1, 0, 'divider'
callback(data)
id: (obj) ->
obj.id
text: (obj) ->
obj.name
toggleLabel: (obj) ->
"#{$groupDropdown.data('default-label')} #{obj.name}"
clicked: =>
@submitSearch()
)
$projectDropdown.glDropdown(
selectable: true
filterable: true
fieldName: 'project_id'
data: (term, callback) ->
Api.projects term, 'id', (data) ->
data.unshift(
name_with_namespace: 'Any'
)
data.splice 1, 0, 'divider'
callback(data)
id: (obj) ->
obj.id
text: (obj) ->
obj.name_with_namespace
toggleLabel: (obj) ->
"#{$projectDropdown.data('default-label')} #{obj.name_with_namespace}"
clicked: =>
@submitSearch()
)
eventListeners: ->
$(document)
.off 'keyup', '.js-search-input'
.on 'keyup', '.js-search-input', @searchKeyUp
$(document)
.off 'click', '.js-search-clear'
.on 'click', '.js-search-clear', @clearSearchField
submitSearch: ->
$('.js-search-form').submit()
searchKeyUp: ->
$input = $(@)
if $input.val() is ''
$('.js-search-clear').addClass 'hidden'
else
$('.js-search-clear').removeClass 'hidden'
clearSearchField: ->
$('.js-search-input')
.val ''
.trigger 'keyup'
.focus()
......@@ -92,7 +92,7 @@ class @UserTabs
@setCurrentAction(action)
activateTab: (action) ->
@parentEl.find(".nav-links .#{action}-tab a").tab('show')
@parentEl.find(".nav-links .js-#{action}-tab a").tab('show')
setTab: (source, action) ->
return if @loaded[action] is true
......
......@@ -25,6 +25,7 @@
@import "framework/lists.scss";
@import "framework/markdown_area.scss";
@import "framework/mobile.scss";
@import "framework/modal.scss";
@import "framework/nav.scss";
@import "framework/pagination.scss";
@import "framework/progress.scss";
......
......@@ -28,6 +28,7 @@
&.s46 { width: 46px; height: 46px; margin-right: 15px; }
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
&.s70 { width: 70px; height: 70px; margin-right: 14px; }
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
&.s110 { width: 110px; height: 110px; margin-right: 15px; }
&.s140 { width: 140px; height: 140px; margin-right: 20px; }
......
.light-well {
background-color: #f8fafc;
background-color: $background-color;
padding: 15px;
}
......@@ -18,7 +18,7 @@
line-height: 36px;
}
.gray-content-block {
.row-content-block {
margin-top: 0;
margin-bottom: -$gl-padding;
background-color: $background-color;
......@@ -81,6 +81,11 @@
margin-left: 10px;
}
}
&.build-content {
background-color: $white-light;
border-top: none;
}
}
.cover-block {
......@@ -113,7 +118,7 @@
line-height: 1.1;
h1 {
color: #313236;
color: $gl-gray-dark;
margin-bottom: 6px;
font-size: 23px;
}
......@@ -150,6 +155,41 @@
right: auto;
}
}
&.groups-cover-block {
background: $white-light;
border-bottom: 1px solid $border-color;
text-align: left;
padding: 24px 0;
.group-info {
.cover-title {
margin-top: 9px;
}
p {
margin-bottom: 0;
}
}
@media (max-width: $screen-xs-max) {
text-align: center;
.avatar {
float: none;
}
}
}
.group-info {
h1 {
display: inline;
font-weight: normal;
font-size: 24px;
color: $gl-title-color;
}
}
}
.block-connector {
......
......@@ -59,7 +59,7 @@
}
@mixin btn-gray {
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, #313236);
@include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, $gl-gray-dark);
}
@mixin btn-white {
......@@ -139,6 +139,10 @@
pointer-events: auto !important;
}
&[disabled] {
pointer-events: none !important;
}
.caret {
margin-left: 5px;
}
......@@ -247,3 +251,10 @@
.btn-file-option {
background: linear-gradient(180deg, $white-light 25%, $gray-light 100%);
}
.btn-build {
margin-left: 10px;
i {
color: $gl-icon-color;
}
}
......@@ -11,6 +11,7 @@
.prepend-top-10 { margin-top: 10px }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top: 20px }
.prepend-left-5 { margin-left: 5px }
.prepend-left-10 { margin-left: 10px }
.prepend-left-default { margin-left: $gl-padding; }
.prepend-left-20 { margin-left: 20px }
......
......@@ -42,7 +42,7 @@
font-size: 15px;
text-align: left;
border: 1px solid $dropdown-toggle-border-color;
border-radius: $dropdown-border-radius;
border-radius: $border-radius-base;
outline: 0;
text-overflow: ellipsis;
white-space: nowrap;
......@@ -80,7 +80,7 @@
padding: 10px 0;
background-color: $dropdown-bg;
border: 1px solid $dropdown-border-color;
border-radius: $dropdown-border-radius;
border-radius: $border-radius-base;
box-shadow: 0 2px 4px $dropdown-shadow-color;
&.is-loading {
......
......@@ -78,6 +78,24 @@ label {
border-radius: 3px;
}
.select-wrapper {
position: relative;
.caret {
position: absolute;
right: 10px;
top: $gl-padding;
color: $gray-darkest;
pointer-events: none;
}
}
.select-control {
padding-left: 10px;
padding-right: 10px;
-webkit-appearance: none;
}
.form-control-inline {
display: inline;
}
......
......@@ -26,9 +26,13 @@ header {
z-index: 100;
margin-bottom: 0;
min-height: $header-height;
background-color: #fff;
background-color: $background-color;
border: none;
border-bottom: 1px solid #eee;
border-bottom: 1px solid $border-color;
&.with-horizontal-nav {
border-bottom: none;
}
.container-fluid {
width: 100% !important;
......@@ -47,7 +51,7 @@ header {
text-align: center;
&:hover, &:focus, &:active {
background-color: #fff;
background-color: $background-color;
}
}
......
......@@ -30,7 +30,7 @@
}
.rss-btn {
display: none !important;
display: none;
}
.project-home-links {
......
.modal-body {
position: relative;
overflow-y: auto;
padding: 15px;
.form-actions {
margin: -$gl-padding+1;
margin-top: 15px;
}
.text-danger {
font-weight: bold;
}
}
body.modal-open {
overflow: hidden;
}
.modal .modal-dialog {
width: 860px;
}
......@@ -26,8 +26,8 @@
}
&.active a {
color: #000;
border-bottom: 2px solid #4688f1;
border-bottom: 2px solid $link-underline-blue;
color: $black;
}
.badge {
......@@ -140,6 +140,12 @@
}
}
.project-filter-form {
input {
background-color: $background-color;
}
}
@media (max-width: $screen-xs-max) {
padding-bottom: 0;
......@@ -185,3 +191,69 @@
}
}
}
.layout-nav {
position: fixed;
top: $header-height;
width: 100%;
z-index: 1;
background: $background-color;
border-bottom: 1px solid $border-color;
transition-duration: .3s;
.controls {
float: right;
padding: 7px 5px 0 0;
i {
color: $layout-link-gray;
}
.fa-rss,
.fa-cog {
font-size: 16px;
}
.fa-caret-down {
margin-left: 5px;
color: $gl-icon-color;
}
.dropdown {
margin-left: 7px;
}
}
.nav-links {
border-bottom: none;
height: 51px;
white-space: nowrap;
overflow-x: auto;
li {
a {
padding-top: 10px;
}
a, i {
color: $layout-link-gray;
}
&.active {
a, i {
color: $black;
}
}
.badge {
color: $gl-icon-color;
}
}
}
}
.page-with-layout-nav {
margin-top: 50px;
}
......@@ -7,13 +7,11 @@
.select2-choice {
background: #fff;
border-color: $input-border;
border-color: $border-white-light;
height: 35px;
padding: $gl-vert-padding $gl-btn-padding;
font-size: $gl-font-size;
line-height: 1.42857143;
@include border-radius($border-radius-default);
border-radius: $border-radius-base;
.select2-arrow {
background-image: none;
......@@ -199,6 +197,14 @@
}
}
.select2-highlighted {
.group-result {
.group-path {
color: #fff;
}
}
}
.group-result {
.group-image {
float: left;
......
......@@ -3,6 +3,7 @@
position: absolute;
width: 58px;
cursor: pointer;
margin-top: 8px;
}
.page-with-sidebar {
......@@ -62,7 +63,7 @@
float: left;
height: $header-height;
width: 100%;
padding: 11px 0 11px 22px;
padding-left: 22px;
overflow: hidden;
outline: none;
transition-duration: .3s;
......@@ -85,7 +86,7 @@
margin: 0;
margin-left: 50px;
font-size: 19px;
line-height: 41px;
line-height: 50px;
font-weight: normal;
}
}
......@@ -254,6 +255,10 @@
}
}
}
.layout-nav {
padding-right: $sidebar_collapsed_width;
}
}
.page-sidebar-expanded {
......@@ -280,6 +285,10 @@
}
}
}
.layout-nav {
padding-right: $sidebar_width;
}
}
.right-sidebar-collapsed {
......
......@@ -32,13 +32,11 @@ table {
th {
background-color: $background-color;
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid $border-color;
border-bottom: none;
}
td {
border-color: $table-border-color;
border-bottom: 1px solid $border-color;
}
}
}
......
......@@ -81,7 +81,7 @@
// Labels
.label {
padding: 2px 4px;
padding: 4px 5px;
font-size: 13px;
font-style: normal;
font-weight: normal;
......
......@@ -153,8 +153,8 @@ $nav-link-padding: 13px $gl-padding;
//== Code
//
//##
$pre-bg: #f8fafc !default;
$pre-bg: $background-color !default;
$pre-color: $gl-gray !default;
$pre-border-color: #e7e9ed;
$pre-border-color: $border-color;
$table-bg-accent: $background-color;
......@@ -42,14 +42,14 @@
margin: 24px 0 12px;
padding: 0 0 10px;
border-bottom: 1px solid #e7e9ed;
color: #313236;
color: $gl-gray-dark;
}
h2 {
font-size: 1.2em;
font-weight: 600;
margin: 24px 0 12px;
color: #313236;
color: $gl-gray-dark;
}
h3 {
......@@ -205,6 +205,10 @@ h1, h2, h3, h4, h5, h6 {
font-weight: 600;
}
.light-header {
font-weight: 600;
}
/** CODE **/
pre {
font-family: $monospace_font;
......@@ -259,3 +263,9 @@ h1, h2, h3, h4 {
color: $gl-gray;
}
}
.text-right-lg {
@media (min-width: $screen-lg-min) {
text-align: right;
}
}
......@@ -12,7 +12,7 @@ $gutter_inner_width: 258px;
*/
$border-color: #e5e5e5;
$focus-border-color: #3aabf0;
$table-border-color: #eef0f2;
$table-border-color: #ececec;
$background-color: #fafafa;
/*
......@@ -20,7 +20,7 @@ $background-color: #fafafa;
*/
$gl-font-size: 15px;
$gl-title-color: #333;
$gl-text-color: #555;
$gl-text-color: #5c5c5c;
$gl-text-green: #4a2;
$gl-text-red: #d12f19;
$gl-text-orange: #d90;
......@@ -30,6 +30,7 @@ $gl-placeholder-color: #8f8f8f;
$gl-icon-color: $gl-placeholder-color;
$gl-grayish-blue: #7f8fa4;
$gl-gray: $gl-text-color;
$gl-gray-dark: #313236;
$gl-header-color: $gl-title-color;
/*
......@@ -65,16 +66,18 @@ $gl-padding-top: 10px;
$row-hover: #f4f8fe;
$progress-color: #c0392b;
$avatar_radius: 50%;
$header-height: 58px;
$header-height: 50px;
$fixed-layout-width: 1280px;
$gl-avatar-size: 40px;
$error-exclamation-point: #e62958;
$border-radius-default: 2px;
$btn-transparent-color: #8f8f8f;
$ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px;
$settings-icon-size: 18px;
$provider-btn-group-border: #e5e5e5;
$provider-btn-not-active-color: #4688f1;
$link-underline-blue: #4a8bee;
$layout-link-gray: #7e7c7c;
$todo-alert-blue: #428bca;
/*
* Color schema
......@@ -109,6 +112,7 @@ $red-light: #e52c5a;
$red-normal: #d22852;
$red-dark: darken($red-normal, 5%);
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
$border-white-light: #f1f2f4;
......@@ -183,7 +187,6 @@ $regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif
/*
* Dropdowns
*/
$dropdown-border-radius: 2px;
$dropdown-width: 300px;
$dropdown-bg: #fff;
$dropdown-link-color: #555;
......
......@@ -83,3 +83,12 @@
}
}
}
table.builds {
.build-link {
a {
color: $gl-dark-link-color;
}
}
}
......@@ -31,9 +31,23 @@
}
.commit-committer-link,
.commit-author-link {
color: #444;
color: $gl-gray;
font-weight: bold;
}
.time_ago {
margin-left: 8px;
}
.fa-clipboard {
color: $dropdown-title-btn-color;
}
.commit-info {
&.branches {
margin-left: 8px;
}
}
}
.commit-box {
......@@ -42,7 +56,7 @@
.commit-title {
margin: 0;
font-size: 23px;
color: #313236;
color: $gl-gray-dark;
}
.commit-description {
......@@ -83,6 +97,14 @@
}
}
.commit-action-buttons {
i {
color: $gl-icon-color;
font-size: 13px;
margin-right: 3px;
}
}
/*
* Commit message textarea for web editor and
* custom merge request message
......
......@@ -22,7 +22,7 @@
.title {
margin: 0;
font-size: 23px;
color: #313236;
color: $gl-gray-dark;
}
.description {
......
......@@ -98,7 +98,11 @@
}
td.line_content.parallel {
width: 50%;
width: 46%;
}
.add-diff-note {
margin-left: -65px;
}
}
......@@ -127,8 +131,13 @@
margin: 0;
padding: 0 0.5em;
border: none;
&.parallel {
display: table-cell;
span {
word-break: break-all;
}
}
}
......
......@@ -55,25 +55,6 @@
}
}
.modal-body {
position: relative;
overflow-y: auto;
padding: 15px;
.form-actions {
margin: -$gl-padding+1;
margin-top: 15px;
}
}
body.modal-open {
overflow: hidden;
}
.modal .modal-dialog {
width: 860px;
}
.documentation {
padding: 7px;
}
......@@ -104,7 +104,7 @@
font-weight: 600;
font-size: 17px;
margin: 5px 0;
color: #313236;
color: $gl-gray-dark;
}
p:last-child {
......@@ -136,7 +136,7 @@
}
.label-branch {
color: #313236;
color: $gl-gray-dark;
font-family: $monospace_font;
font-weight: bold;
overflow: hidden;
......@@ -272,3 +272,19 @@
display: inline-block;
width: 250px;
}
.table-holder {
.builds {
th {
background-color: $white-light;
color: $gl-placeholder-color;
}
th,
td {
padding: 16px;
}
}
}
......@@ -28,7 +28,7 @@ li.milestone {
// Issue title
span a {
color: rgba(0,0,0,0.64);
color: $gl-text-color;
}
}
}
......@@ -51,7 +51,7 @@ li.milestone {
margin-top: 7px;
.issuable-number {
color: rgba(0,0,0,0.44);
color: $gl-placeholder-color;
margin-right: 5px;
}
.avatar {
......
......@@ -114,10 +114,6 @@ ul.notes {
word-break: keep-all;
}
}
a {
word-break: break-all;
}
}
.note-header {
......@@ -172,6 +168,11 @@ ul.notes {
.notes {
background-color: $white-light;
}
a code {
top: 0;
margin-right: 0;
}
}
}
}
......@@ -215,7 +216,7 @@ ul.notes {
}
.discussion-actions {
@media (max-width: $screen-sm-max) {
@media (max-width: $screen-md-max) {
float: none;
margin-left: 0;
......
......@@ -18,7 +18,8 @@
}
.account-btn-link,
.profile-settings-sidebar a {
.profile-settings-sidebar a,
.settings-sidebar a {
color: $md-link-color;
}
......@@ -123,12 +124,6 @@
}
}
.key-icon {
color: $ssh-key-icon-color;
font-size: $ssh-key-icon-size;
line-height: 42px;
}
.key-created-at {
line-height: 42px;
}
......@@ -180,14 +175,6 @@
}
}
.profile-settings-message {
line-height: 32px;
color: $warning-message-color;
background-color: $warning-message-bg;
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
.oauth-applications {
form {
display: inline-block;
......@@ -218,3 +205,21 @@
text-align: center;
}
}
.user-profile {
@media (max-width: $screen-xs-max) {
.cover-block {
padding-top: 20px;
}
.cover-controls {
position: static;
margin-bottom: 20px;
.btn {
display: inline-block;
width: 48%;
}
}
}
}
......@@ -178,7 +178,7 @@
.option-title {
font-weight: normal;
display: inline-block;
color: #313236;
color: $gl-gray-dark;
}
.option-descr {
......@@ -202,8 +202,31 @@
min-width: 200px;
}
.deploy-project-label {
margin: 1px;
.deploy-key-content {
@media (min-width: $screen-sm-min) {
float: left;
&:last-child {
float: right;
}
}
}
.deploy-key-projects {
@media (min-width: $screen-sm-min) {
line-height: 42px;
}
}
a.deploy-project-label {
padding: 5px;
margin-right: 5px;
color: $gl-gray;
background-color: $row-hover;
&:hover {
color: $gl-link-color;
}
}
.vs-public {
......@@ -256,12 +279,6 @@
}
}
table.table.protected-branches-list tr.no-border {
th, td {
border: 0;
}
}
.project-import .btn {
float: left;
margin-right: 10px;
......@@ -474,3 +491,14 @@ pre.light-well {
color: #fff;
}
}
.protected-branches-list {
a {
color: $gl-gray;
font-weight: 600;
&:hover {
color: $gl-link-color;
}
}
}
......@@ -10,17 +10,6 @@
}
}
.search-holder {
max-width: 600px;
margin: 0 auto;
margin-bottom: 20px;
input {
border-color: #bbb;
font-weight: bold;
}
}
.search {
margin-right: 10px;
margin-left: 10px;
......@@ -159,7 +148,85 @@
&.has-location-badge {
.search-input-wrap {
width: 78%;
width: 68%;
}
}
}
.search-holder {
@media (min-width: $screen-sm-min) {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.search-field-holder {
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
position: relative;
margin-right: 0;
@media (min-width: $screen-sm-min) {
margin-right: 5px;
}
}
.search-icon {
position: absolute;
left: 10px;
top: 10px;
color: $gray-darkest;
pointer-events: none;
}
.search-text-input {
padding-left: $gl-padding + 15px;
padding-right: $gl-padding + 15px;
}
.btn-search {
width: 100%;
margin-top: 5px;
@media (min-width: $screen-sm-min) {
width: auto;
margin-top: 0;
margin-left: 5px;
}
}
.dropdown {
@media (min-width: $screen-sm-min) {
margin-left: 5px;
margin-right: 5px;
}
}
.dropdown-menu-toggle {
width: 100%;
margin-top: 5px;
@media (min-width: $screen-sm-min) {
width: 160px;
margin-top: 0;
}
}
}
.search-clear {
position: absolute;
right: 10px;
top: 10px;
padding: 0;
color: $gray-darkest;
line-height: 0;
background: none;
border: 0;
&:hover,
&:focus {
color: $gl-link-color;
outline: none;
}
}
.settings-list-icon {
color: $gl-placeholder-color;
font-size: $settings-icon-size;
line-height: 42px;
}
.settings-message {
padding: 5px;
line-height: 1.3;
color: $warning-message-color;
background-color: $warning-message-bg;
border: 1px solid $warning-message-border;
border-radius: $border-radius-base;
}
.container-fluid {
.ci-status {
padding: 2px 7px;
margin-right: 5px;
margin-right: 10px;
border: 1px solid #eee;
white-space: nowrap;
@include border-radius(4px);
......
......@@ -6,9 +6,16 @@
.navbar-nav {
li {
.badge.todos-pending-count {
background-color: $gl-icon-color;
margin-top: -5px;
font-weight: normal;
background: $todo-alert-blue;
margin-left: -17px;
font-size: 11px;
color: white;
padding: 3px;
padding-top: 1px;
padding-bottom: 1px;
border-radius: 3px;
}
}
}
......
......@@ -16,7 +16,7 @@
tr {
> td, > th {
line-height: 26px;
line-height: 23px;
}
&:hover {
......
......@@ -6,12 +6,6 @@ class Admin::ApplicationController < ApplicationController
layout 'admin'
def authenticate_admin!
return render_404 unless current_user.is_admin?
end
def authorize_impersonator!
if session[:impersonator_id]
User.find_by!(username: session[:impersonator_id]).admin?
end
render_404 unless current_user.is_admin?
end
end
......@@ -39,6 +39,12 @@ class Admin::HooksController < Admin::ApplicationController
end
def hook_params
params.require(:hook).permit(:url, :enable_ssl_verification, :push_events, :tag_push_events)
params.require(:hook).permit(
:enable_ssl_verification,
:push_events,
:tag_push_events,
:token,
:url
)
end
end
class Admin::ImpersonationController < Admin::ApplicationController
skip_before_action :authenticate_admin!, only: :destroy
before_action :user
before_action :authorize_impersonator!
def create
if @user.blocked?
flash[:alert] = "You cannot impersonate a blocked user"
redirect_to admin_user_path(@user)
else
session[:impersonator_id] = current_user.username
session[:impersonator_return_to] = admin_user_path(@user)
warden.set_user(user, scope: 'user')
flash[:alert] = "You are impersonating #{user.username}."
redirect_to root_path
end
end
def destroy
redirect = session[:impersonator_return_to]
warden.set_user(user, scope: 'user')
session[:impersonator_return_to] = nil
session[:impersonator_id] = nil
redirect_to redirect || root_path
end
def user
@user ||= User.find_by!(username: params[:id] || session[:impersonator_id])
end
end
class Admin::ImpersonationsController < Admin::ApplicationController
skip_before_action :authenticate_admin!
before_action :authenticate_impersonator!
def destroy
original_user = current_user
warden.set_user(impersonator, scope: :user)
Gitlab::AppLogger.info("User #{original_user.username} has stopped impersonating #{impersonator.username}")
session[:impersonator_id] = nil
redirect_to admin_user_path(original_user)
end
private
def impersonator
@impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
end
def authenticate_impersonator!
render_404 unless impersonator && impersonator.is_admin? && !impersonator.blocked?
end
end
......@@ -31,6 +31,24 @@ class Admin::UsersController < Admin::ApplicationController
user
end
def impersonate
if user.blocked?
flash[:alert] = "You cannot impersonate a blocked user"
redirect_to admin_user_path(user)
else
session[:impersonator_id] = current_user.id
warden.set_user(user, scope: :user)
Gitlab::AppLogger.info("User #{current_user.username} has started impersonating #{user.username}")
flash[:alert] = "You are now impersonating #{user.username}"
redirect_to root_path
end
end
def block
if user.block
redirect_back_or_admin_user(notice: "Successfully blocked")
......
......@@ -117,7 +117,7 @@ class ApplicationController < ActionController::Base
end
def after_sign_out_path_for(resource)
current_application_settings.after_sign_out_path || new_user_session_path
current_application_settings.after_sign_out_path.presence || new_user_session_path
end
def abilities
......
......@@ -15,7 +15,7 @@ class Projects::CommitsController < Projects::ApplicationController
if search.present?
@repository.find_commits_by_message(search, @ref, @path, @limit, @offset).compact
else
@repository.commits(@ref, @path, @limit, @offset)
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
end
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
......
......@@ -7,31 +7,24 @@ class Projects::DeployKeysController < Projects::ApplicationController
layout "project_settings"
def index
@enabled_keys = @project.deploy_keys
@available_keys = accessible_keys - @enabled_keys
@available_project_keys = current_user.project_deploy_keys - @enabled_keys
@available_public_keys = DeployKey.are_public - @enabled_keys
# Public keys that are already used by another accessible project are already
# in @available_project_keys.
@available_public_keys -= @available_project_keys
@key = DeployKey.new
set_index_vars
end
def new
@key = @project.deploy_keys.new
respond_with(@key)
redirect_to namespace_project_deploy_keys_path(@project.namespace,
@project)
end
def create
@key = DeployKey.new(deploy_key_params)
set_index_vars
if @key.valid? && @project.deploy_keys << @key
redirect_to namespace_project_deploy_keys_path(@project.namespace,
@project)
else
render "new"
render "index"
end
end
......@@ -51,6 +44,18 @@ class Projects::DeployKeysController < Projects::ApplicationController
protected
def set_index_vars
@enabled_keys ||= @project.deploy_keys
@available_keys ||= accessible_keys - @enabled_keys
@available_project_keys ||= current_user.project_deploy_keys - @enabled_keys
@available_public_keys ||= DeployKey.are_public - @enabled_keys
# Public keys that are already used by another accessible project are already
# in @available_project_keys.
@available_public_keys -= @available_project_keys
end
def accessible_keys
@accessible_keys ||= current_user.accessible_deploy_keys
end
......
......@@ -17,7 +17,7 @@ class Projects::GraphsController < Projects::ApplicationController
end
def commits
@commits = @project.repository.commits(@ref, nil, 2000, 0, true)
@commits = @project.repository.commits(@ref, limit: 2000, skip_merges: true)
@commits_graph = Gitlab::Graphs::Commits.new(@commits)
@commits_per_week_days = @commits_graph.commits_per_week_days
@commits_per_time = @commits_graph.commits_per_time
......@@ -55,7 +55,7 @@ class Projects::GraphsController < Projects::ApplicationController
private
def fetch_graph
@commits = @project.repository.commits(@ref, nil, 6000, 0, true)
@commits = @project.repository.commits(@ref, limit: 6000, skip_merges: true)
@log = []
@commits.each do |commit|
......
......@@ -52,8 +52,16 @@ class Projects::HooksController < Projects::ApplicationController
end
def hook_params
params.require(:hook).permit(:url, :push_events, :issues_events,
:merge_requests_events, :tag_push_events, :note_events,
:build_events, :enable_ssl_verification)
params.require(:hook).permit(
:build_events,
:enable_ssl_verification,
:issues_events,
:merge_requests_events,
:note_events,
:push_events,
:tag_push_events,
:token,
:url
)
end
end
......@@ -3,8 +3,8 @@ class Projects::IssuesController < Projects::ApplicationController
include IssuableActions
before_action :module_enabled
before_action :issue,
only: [:edit, :update, :show, :referenced_merge_requests, :related_branches]
before_action :issue, only: [:edit, :update, :show, :referenced_merge_requests,
:related_branches, :can_create_branch]
# Allow read any issue
before_action :authorize_read_issue!, only: [:show]
......@@ -96,6 +96,8 @@ class Projects::IssuesController < Projects::ApplicationController
if params[:move_to_project_id].to_i > 0
new_project = Project.find(params[:move_to_project_id])
return render_404 unless issue.can_move?(current_user, new_project)
move_service = Issues::MoveService.new(project, current_user)
@issue = move_service.execute(@issue, new_project)
end
......@@ -139,6 +141,18 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
def can_create_branch
can_create = current_user &&
can?(current_user, :push_code, @project) &&
@issue.can_be_worked_on?(current_user)
respond_to do |format|
format.json do
render json: { can_create_branch: can_create }
end
end
end
def bulk_update
result = Issues::BulkUpdateService.new(project, current_user, bulk_update_params).execute
redirect_back_or_default(default: { action: 'index' }, options: { notice: "#{result[:count]} issues updated" })
......
......@@ -40,10 +40,10 @@ class Projects::WikisController < Projects::ApplicationController
end
def update
@page = @project_wiki.find_page(params[:id])
return render('empty') unless can?(current_user, :create_wiki, @project)
@page = @project_wiki.find_page(params[:id])
if @page = WikiPages::UpdateService.new(@project, current_user, wiki_params).execute(@page)
redirect_to(
namespace_project_wiki_path(@project.namespace, @project, @page),
......
......@@ -8,6 +8,13 @@ class RegistrationsController < Devise::RegistrationsController
def create
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
# To avoid duplicate form fields on the login page, the registration form
# names fields using `new_user`, but Devise still wants the params in
# `user`.
if params["new_#{resource_name}"].present? && params[resource_name].blank?
params[resource_name] = params.delete(:"new_#{resource_name}")
end
super
else
flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code."
......
......@@ -8,8 +8,6 @@ class SearchController < ApplicationController
def show
return if params[:search].nil? || params[:search].blank?
@search_term = params[:search]
if params[:project_id].present?
@project = Project.find_by(id: params[:project_id])
@project = nil unless can?(current_user, :download_code, @project)
......@@ -20,6 +18,8 @@ class SearchController < ApplicationController
@group = nil unless can?(current_user, :read_group, @group)
end
@search_term = params[:search]
@scope = params[:scope]
@show_snippets = params[:snippets].eql? 'true'
......@@ -44,7 +44,7 @@ class SearchController < ApplicationController
Search::GlobalService.new(current_user, params).execute
end
@objects = @search_results.objects(@scope, params[:page])
@search_objects = @search_results.objects(@scope, params[:page])
end
def autocomplete
......
......@@ -51,7 +51,7 @@ class SnippetsFinder
snippets = project.snippets.fresh
if current_user
if project.team.member?(current_user.id)
if project.team.member?(current_user.id) || current_user.admin?
snippets
else
snippets.public_and_internal
......
......@@ -3,8 +3,8 @@ module BlobHelper
Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap)
end
def highlight(blob_name, blob_content, nowrap: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap)
def highlight(blob_name, blob_content, nowrap: false, plain: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain)
end
def no_highlight_files
......@@ -131,7 +131,7 @@ module BlobHelper
# elements and attributes. Note that this whitelist is by no means complete
# and may omit some elements.
def sanitize_svg(blob)
blob.data = Loofah.scrub_fragment(blob.data, :strip).to_xml
blob.data = Gitlab::Sanitizers::SVG.clean(blob.data)
blob
end
......
module CiBadgeHelper
def markdown_badge_code(project, ref)
url = status_ci_project_url(project, ref: ref, format: 'png')
link = namespace_project_commits_path(project.namespace, project, ref)
"[![build status](#{url})](#{link})"
end
def html_badge_code(project, ref)
url = status_ci_project_url(project, ref: ref, format: 'png')
link = namespace_project_commits_path(project.namespace, project, ref)
"<a href='#{link}'><img src='#{url}' /></a>"
end
end
......@@ -23,7 +23,7 @@ module DiffHelper
end
def diff_options
options = { ignore_whitespace_change: params[:w] == '1' }
options = { ignore_whitespace_change: hide_whitespace? }
if diff_hard_limit_enabled?
options.merge!(Commit.max_diff_options)
end
......@@ -128,4 +128,31 @@ module DiffHelper
title
end
end
def commit_diff_whitespace_link(project, commit, options)
url = namespace_project_commit_path(project.namespace, project, commit.id, params_with_whitespace)
toggle_whitespace_link(url, options)
end
def diff_merge_request_whitespace_link(project, merge_request, options)
url = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request, params_with_whitespace)
toggle_whitespace_link(url, options)
end
private
def hide_whitespace?
params[:w] == '1'
end
def params_with_whitespace
hide_whitespace? ? request.query_parameters.except(:w) : request.query_parameters.merge(w: 1)
end
def toggle_whitespace_link(url, options)
options[:class] ||= ''
options[:class] << ' btn btn-default'
link_to "#{hide_whitespace? ? 'Show' : 'Hide'} whitespace changes", url, class: options[:class]
end
end
......@@ -16,31 +16,49 @@ module IssuesHelper
def url_for_project_issues(project = @project, options = {})
return '' if project.nil?
if options[:only_path]
project.issues_tracker.project_path
else
project.issues_tracker.project_url
end
url =
if options[:only_path]
project.issues_tracker.project_path
else
project.issues_tracker.project_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_new_issue(project = @project, options = {})
return '' if project.nil?
if options[:only_path]
project.issues_tracker.new_issue_path
else
project.issues_tracker.new_issue_url
end
url =
if options[:only_path]
project.issues_tracker.new_issue_path
else
project.issues_tracker.new_issue_url
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def url_for_issue(issue_iid, project = @project, options = {})
return '' if project.nil?
if options[:only_path]
project.issues_tracker.issue_path(issue_iid)
else
project.issues_tracker.issue_url(issue_iid)
end
url =
if options[:only_path]
project.issues_tracker.issue_path(issue_iid)
else
project.issues_tracker.issue_url(issue_iid)
end
# Ensure we return a valid URL to prevent possible XSS.
URI.parse(url).to_s
rescue URI::InvalidURIError
''
end
def bulk_update_milestone_options
......
......@@ -37,7 +37,7 @@ module LabelsHelper
link = send("namespace_project_#{type.to_s.pluralize}_path",
project.namespace,
project,
label_name: label.name)
label_name: [label.name])
if block_given?
link_to link, &block
......
......@@ -34,10 +34,13 @@ module NavHelper
end
def nav_header_class
if nav_menu_collapsed?
"header-collapsed"
else
"header-expanded"
end
class_name =
if nav_menu_collapsed?
"header-collapsed"
else
"header-expanded"
end
class_name += " with-horizontal-nav" if defined?(nav) && nav
class_name
end
end
......@@ -200,12 +200,8 @@ module ProjectsHelper
end
def repository_size(project = @project)
"#{project.repository_size} MB"
rescue
# In order to prevent 500 error
# when application cannot allocate memory
# to calculate repo size - just show 'Unknown'
'unknown'
size_in_bytes = project.repository_size * 1.megabyte
number_to_human_size(size_in_bytes, delimiter: ',', precision: 2)
end
def default_url_to_repo(project = @project)
......@@ -341,4 +337,10 @@ module ProjectsHelper
)
end
end
def sanitize_repo_path(message)
return '' unless message.present?
message.strip.gsub(Gitlab.config.gitlab_shell.repos_path.chomp('/'), "[REPOS PATH]")
end
end
......@@ -19,6 +19,16 @@ module SearchHelper
end
end
def search_entries_info(collection, scope, term)
return unless collection.count > 0
from = collection.offset_value + 1
to = collection.offset_value + collection.length
count = collection.total_count
"Showing #{from} - #{to} of #{count} #{scope.humanize(capitalize: false)} for \"#{term}\""
end
private
# Autocomplete results for various settings pages
......
......@@ -28,6 +28,14 @@ module Emails
mail_answer_thread(@merge_request, note_thread_options(recipient_id))
end
def note_snippet_email(recipient_id, note_id)
setup_note_mail(note_id, recipient_id)
@snippet = @note.noteable
@target_url = namespace_project_snippet_url(*note_target_url_options)
mail_answer_thread(@snippet, note_thread_options(recipient_id))
end
private
def note_target_url_options
......
# == Schema Information
#
# Table name: appearances
#
# id :integer not null, primary key
# title :string
# description :text
# header_logo :string
# logo :string
# created_at :datetime not null
# updated_at :datetime not null
#
class Appearance < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
......
......@@ -10,21 +10,20 @@
# sign_in_text :text
# created_at :datetime
# updated_at :datetime
# home_page_url :string(255)
# home_page_url :string
# default_branch_protection :integer default(2)
# restricted_visibility_levels :text
# version_check_enabled :boolean default(TRUE)
# max_attachment_size :integer default(10), not null
# default_project_visibility :integer
# default_snippet_visibility :integer
# default_group_visibility :integer
# restricted_signup_domains :text
# user_oauth_applications :boolean default(TRUE)
# after_sign_out_path :string(255)
# after_sign_out_path :string
# session_expire_delay :integer default(10080), not null
# import_sources :text
# help_page_text :text
# admin_notification_email :string(255)
# admin_notification_email :string
# shared_runners_enabled :boolean default(TRUE), not null
# max_artifacts_size :integer default(100), not null
# runners_registration_token :string
......@@ -32,8 +31,6 @@
# two_factor_grace_period :integer default(48)
# metrics_enabled :boolean default(FALSE)
# metrics_host :string default("localhost")
# metrics_username :string
# metrics_password :string
# metrics_pool_size :integer default(16)
# metrics_timeout :integer default(10)
# metrics_method_call_threshold :integer default(10)
......@@ -41,9 +38,16 @@
# recaptcha_site_key :string
# recaptcha_private_key :string
# metrics_port :integer default(8089)
# metrics_sample_interval :integer default(15)
# sentry_enabled :boolean default(FALSE)
# sentry_dsn :string
# akismet_enabled :boolean default(FALSE)
# akismet_api_key :string
# email_author_in_body :boolean default(FALSE)
# default_group_visibility :integer
# repository_checks_enabled :boolean default(FALSE)
# metrics_packet_size :integer default(1)
# shared_runners_text :text
#
class ApplicationSetting < ActiveRecord::Base
......
......@@ -4,9 +4,9 @@
#
# id :integer not null, primary key
# author_id :integer not null
# type :string(255) not null
# type :string not null
# entity_id :integer not null
# entity_type :string(255) not null
# entity_type :string not null
# details :text
# created_at :datetime
# updated_at :datetime
......
......@@ -19,6 +19,14 @@ class Blob < SimpleDelegator
new(blob)
end
def no_highlighting?
size && size > 1.megabyte
end
def only_display_raw?
size && size > 5.megabytes
end
def svg?
text? && language && language.name == 'SVG'
end
......
......@@ -8,8 +8,8 @@
# ends_at :datetime
# created_at :datetime
# updated_at :datetime
# color :string(255)
# font :string(255)
# color :string
# font :string
#
class BroadcastMessage < ActiveRecord::Base
......
......@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
# status :string(255)
# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
......@@ -15,19 +15,19 @@
# commit_id :integer
# commands :text
# job_id :integer
# name :string(255)
# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
# stage :string(255)
# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
# ref :string(255)
# ref :string
# user_id :integer
# type :string(255)
# target_url :string(255)
# description :string(255)
# type :string
# target_url :string
# description :string
# artifacts_file :text
# gl_project_id :integer
# artifacts_metadata :text
......
......@@ -4,9 +4,9 @@
#
# id :integer not null, primary key
# project_id :integer
# ref :string(255)
# sha :string(255)
# before_sha :string(255)
# ref :string
# sha :string
# before_sha :string
# push_data :text
# created_at :datetime
# updated_at :datetime
......@@ -14,6 +14,10 @@
# yaml_errors :text
# committed_at :datetime
# gl_project_id :integer
# status :string
# started_at :datetime
# finished_at :datetime
# duration :integer
#
module Ci
......
......@@ -3,18 +3,18 @@
# Table name: ci_runners
#
# id :integer not null, primary key
# token :string(255)
# token :string
# created_at :datetime
# updated_at :datetime
# description :string(255)
# description :string
# contacted_at :datetime
# active :boolean default(TRUE), not null
# is_shared :boolean default(FALSE)
# name :string(255)
# version :string(255)
# revision :string(255)
# platform :string(255)
# architecture :string(255)
# name :string
# version :string
# revision :string
# platform :string
# architecture :string
#
module Ci
......
......@@ -3,7 +3,7 @@
# Table name: ci_triggers
#
# id :integer not null, primary key
# token :string(255)
# token :string
# project_id :integer
# deleted_at :datetime
# created_at :datetime
......
......@@ -4,11 +4,11 @@
#
# id :integer not null, primary key
# project_id :integer
# key :string(255)
# key :string
# value :text
# encrypted_value :text
# encrypted_value_salt :string(255)
# encrypted_value_iv :string(255)
# encrypted_value_salt :string
# encrypted_value_iv :string
# gl_project_id :integer
#
......
......@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
# status :string(255)
# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
......@@ -15,21 +15,24 @@
# commit_id :integer
# commands :text
# job_id :integer
# name :string(255)
# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
# stage :string(255)
# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
# ref :string(255)
# ref :string
# user_id :integer
# type :string(255)
# target_url :string(255)
# description :string(255)
# type :string
# target_url :string
# description :string
# artifacts_file :text
# gl_project_id :integer
# artifacts_metadata :text
# erased_by_id :integer
# erased_at :datetime
#
class CommitStatus < ActiveRecord::Base
......
......@@ -35,13 +35,14 @@ module Issuable
scope :only_opened, -> { with_state(:opened) }
scope :only_reopened, -> { with_state(:reopened) }
scope :closed, -> { with_state(:closed) }
scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') }
scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') }
scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') }
scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") }
delegate :name,
:email,
......
......@@ -8,7 +8,7 @@ module Milestoneish
end
def complete?(user = nil)
total_items_count(user) == closed_items_count(user)
total_items_count(user) > 0 && total_items_count(user) == closed_items_count(user)
end
def percent_complete(user = nil)
......
......@@ -18,7 +18,7 @@ module Statuseable
WHEN (#{builds})=0 THEN NULL
WHEN (#{builds})=(#{success})+(#{ignored}) THEN 'success'
WHEN (#{builds})=(#{pending}) THEN 'pending'
WHEN (#{builds})=(#{canceled}) THEN 'canceled'
WHEN (#{builds})=(#{canceled})+(#{success})+(#{ignored}) THEN 'canceled'
WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{running})+(#{pending})>0 THEN 'running'
ELSE 'failed'
......
......@@ -7,9 +7,9 @@
# created_at :datetime
# updated_at :datetime
# key :text
# title :string(255)
# type :string(255)
# fingerprint :string(255)
# title :string
# type :string
# fingerprint :string
# public :boolean default(FALSE), not null
#
......
......@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# user_id :integer not null
# email :string(255) not null
# email :string not null
# created_at :datetime
# updated_at :datetime
#
......
......@@ -3,9 +3,9 @@
# Table name: events
#
# id :integer not null, primary key
# target_type :string(255)
# target_type :string
# target_id :integer
# title :string(255)
# title :string
# data :text
# project_id :integer
# created_at :datetime
......
......@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
# status :string(255)
# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
......@@ -15,21 +15,24 @@
# commit_id :integer
# commands :text
# job_id :integer
# name :string(255)
# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
# stage :string(255)
# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
# ref :string(255)
# ref :string
# user_id :integer
# type :string(255)
# target_url :string(255)
# description :string(255)
# type :string
# target_url :string
# description :string
# artifacts_file :text
# gl_project_id :integer
# artifacts_metadata :text
# erased_by_id :integer
# erased_at :datetime
#
class GenericCommitStatus < CommitStatus
......
......@@ -2,16 +2,17 @@
#
# Table name: namespaces
#
# id :integer not null, primary key
# name :string(255) not null
# path :string(255) not null
# owner_id :integer
# visibility_level :integer default(20), not null
# created_at :datetime
# updated_at :datetime
# type :string(255)
# description :string(255) default(""), not null
# avatar :string(255)
# id :integer not null, primary key
# name :string not null
# path :string not null
# owner_id :integer
# created_at :datetime
# updated_at :datetime
# type :string
# description :string default(""), not null
# avatar :string
# share_with_group_lock :boolean default(FALSE)
# visibility_level :integer default(20), not null
#
require 'carrierwave/orm/activerecord'
......
......@@ -16,6 +16,8 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
# wiki_page_events :boolean default(FALSE), not null
# token :string
#
class ProjectHook < WebHook
......
......@@ -16,6 +16,8 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
# wiki_page_events :boolean default(FALSE), not null
# token :string
#
class ServiceHook < WebHook
......
......@@ -16,6 +16,8 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
# wiki_page_events :boolean default(FALSE), not null
# token :string
#
class SystemHook < WebHook
......
......@@ -16,6 +16,8 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
# wiki_page_events :boolean default(FALSE), not null
# token :string
#
class WebHook < ActiveRecord::Base
......@@ -43,23 +45,17 @@ class WebHook < ActiveRecord::Base
if parsed_url.userinfo.blank?
response = WebHook.post(url,
body: data.to_json,
headers: {
"Content-Type" => "application/json",
"X-Gitlab-Event" => hook_name.singularize.titleize
},
headers: build_headers(hook_name),
verify: enable_ssl_verification)
else
post_url = url.gsub("#{parsed_url.userinfo}@", "")
post_url = url.gsub("#{parsed_url.userinfo}@", '')
auth = {
username: CGI.unescape(parsed_url.user),
password: CGI.unescape(parsed_url.password),
}
response = WebHook.post(post_url,
body: data.to_json,
headers: {
"Content-Type" => "application/json",
"X-Gitlab-Event" => hook_name.singularize.titleize
},
headers: build_headers(hook_name),
verify: enable_ssl_verification,
basic_auth: auth)
end
......@@ -73,4 +69,15 @@ class WebHook < ActiveRecord::Base
def async_execute(data, hook_name)
Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data, hook_name)
end
private
def build_headers(hook_name)
headers = {
'Content-Type' => 'application/json',
'X-Gitlab-Event' => hook_name.singularize.titleize
}
headers['X-Gitlab-Token'] = token if token.present?
headers
end
end
......@@ -3,8 +3,8 @@
# Table name: identities
#
# id :integer not null, primary key
# extern_uid :string(255)
# provider :string(255)
# extern_uid :string
# provider :string
# user_id :integer
# created_at :datetime
# updated_at :datetime
......
......@@ -3,20 +3,23 @@
# Table name: issues
#
# id :integer not null, primary key
# title :string(255)
# title :string
# assignee_id :integer
# author_id :integer
# project_id :integer
# created_at :datetime
# updated_at :datetime
# position :integer default(0)
# branch_name :string(255)
# branch_name :string
# description :text
# milestone_id :integer
# state :string(255)
# state :string
# iid :integer
# updated_by_id :integer
# moved_to_id :integer
# confidential :boolean default(FALSE)
# deleted_at :datetime
# due_date :date
#
require 'carrierwave/orm/activerecord'
......
......@@ -7,9 +7,9 @@
# created_at :datetime
# updated_at :datetime
# key :text
# title :string(255)
# type :string(255)
# fingerprint :string(255)
# title :string
# type :string
# fingerprint :string
# public :boolean default(FALSE), not null
#
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment