Merge remote-tracking branch 'upstream/master' into save-artifacts_sizes
* upstream/master: (175 commits) Document Repository#keep_around Don't garbage collect commits that have related DB records like comments Update CHANGELOG Update RedCloth to 4.3.2 for CVE-2012-6684 Fix typo in Merge Requests API documentation Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq Enable Style/EmptyLines cop, remove redundant ones Update CHANGELOG Cache results from jQuery selectors to retrieve namespace name Fix import button when import fail due the namespace already been taken Fix snippets comments not displayed Fix emoji paths in relative root configurations Exclude requesters from Project#members, Group#members and User#members Upgrade Thin from 1.6.1 to 1.7.0. Many squashed commits Cache autocomplete results Upgrade Sidekiq from 4.1.2 to 4.1.4. Upgrade seed-fu from 2.3.5 to 2.3.6 use has_many relationship with events Support creating a todo on issuables via API ...
|
@ -18,6 +18,7 @@ variables:
|
|||
SIMPLECOV: "true"
|
||||
USE_DB: "true"
|
||||
USE_BUNDLE_INSTALL: "true"
|
||||
GIT_DEPTH: "20"
|
||||
|
||||
before_script:
|
||||
- source ./scripts/prepare_build.sh
|
||||
|
|
12
.rubocop.yml
|
@ -1,4 +1,6 @@
|
|||
require: rubocop-rspec
|
||||
require:
|
||||
- rubocop-rspec
|
||||
- ./rubocop/rubocop
|
||||
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.1
|
||||
|
@ -191,7 +193,7 @@ Style/EmptyLineBetweenDefs:
|
|||
|
||||
# Don't use several empty lines in a row.
|
||||
Style/EmptyLines:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Keep blank lines around access modifiers.
|
||||
Style/EmptyLinesAroundAccessModifier:
|
||||
|
@ -532,11 +534,11 @@ Style/SingleLineMethods:
|
|||
|
||||
# Use spaces after colons.
|
||||
Style/SpaceAfterColon:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Use spaces after commas.
|
||||
Style/SpaceAfterComma:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Do not put a space between a method name and the opening parenthesis in a
|
||||
# method definition.
|
||||
|
@ -679,7 +681,7 @@ Style/UnlessElse:
|
|||
|
||||
# Checks for %W when interpolation is not needed.
|
||||
Style/UnneededCapitalW:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# TODO: Enable UnneededInterpolation Cop.
|
||||
# Checks for strings that are just an interpolated expression.
|
||||
|
|
77
CHANGELOG
|
@ -1,20 +1,78 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.10.0 (unreleased)
|
||||
- Fix commit builds API, return all builds for all pipelines for given commit. !4849
|
||||
- Replace Haml with Hamlit to make view rendering faster. !3666
|
||||
- Refactor repository paths handling to allow multiple git mount points
|
||||
- Add Application Setting to configure default Repository Path for new projects
|
||||
- Wrap code blocks on Activies and Todos page. !4783 (winniehell)
|
||||
- Align flash messages with left side of page content !4959 (winniehell)
|
||||
- Display last commit of deleted branch in push events !4699 (winniehell)
|
||||
- Apply the trusted_proxies config to the rack request object for use with rack_attack
|
||||
- Add Sidekiq queue duration to transaction metrics.
|
||||
- Add a new column `artifacts_size` to table `ci_builds` !4964
|
||||
- Let Workhorse serve format-patch diffs
|
||||
- Make images fit to the size of the viewport !4810
|
||||
- Fix check for New Branch button on Issue page !4630 (winniehell)
|
||||
- Fix MR-auto-close text added to description. !4836
|
||||
- Fix pagination when sorting by columns with lots of ties (like priority)
|
||||
- Exclude email check from the standard health check
|
||||
- Fix changing issue state columns in milestone view
|
||||
- Add notification settings dropdown for groups
|
||||
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
|
||||
- API: Todos !3188 (Robert Schilling)
|
||||
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
|
||||
- PipelinesFinder uses git cache data
|
||||
- Check for conflicts with existing Project's wiki path when creating a new project.
|
||||
- Don't instantiate a git tree on Projects show default view
|
||||
- Remove unused front-end variable -> default_issues_tracker
|
||||
- Better caching of git calls on ProjectsController#show.
|
||||
- Add API endpoint for a group issues !4520 (mahcsig)
|
||||
- Add Bugzilla integration !4930 (iamtjg)
|
||||
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
|
||||
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
|
||||
- Add basic system information like memory and disk usage to the admin panel
|
||||
- Don't garbage collect commits that have related DB records like comments
|
||||
|
||||
v 8.9.5 (unreleased)
|
||||
- Improve the request / withdraw access button. !4860
|
||||
- Fix assigning shared runners as admins. !4961
|
||||
- Show "locked" label for locked runners on runners admin. !4961
|
||||
- Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq
|
||||
- Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1
|
||||
- Fix import button disabled when import process fail due to the namespace already been taken.
|
||||
- Security: Update RedCloth to 4.3.2 (Takuya Noguchi)
|
||||
|
||||
v 8.9.4
|
||||
- Fix privilege escalation issue with OAuth external users.
|
||||
- Ensure references to private repos aren't shown to logged-out users.
|
||||
- Fixed search field blur not removing focus. !4704
|
||||
- Resolve "Sub nav isn't showing on file view". !4890
|
||||
- Fixes middle click and double request when navigating through the file browser. !4891
|
||||
- Fixed URL on label button when filtering. !4897
|
||||
- Fixed commit avatar alignment. !4933
|
||||
- Do not show build retry link when build is active. !4967
|
||||
- Fix restore Rake task warning message output. !4980
|
||||
- Handle external issues in IssueReferenceFilter. !4988
|
||||
- Expiry date on pinned nav cookie. !5009
|
||||
- Updated breakpoint for sidebar pinning. !5019
|
||||
|
||||
v 8.9.3
|
||||
- Fix encrypted data backwards compatibility after upgrading attr_encrypted gem. !4963
|
||||
- Fix rendering of commit notes. !4953
|
||||
- Resolve "Pin should show up at 1280px min". !4947
|
||||
- Switched mobile button icons to ellipsis and angle. !4944
|
||||
- Correctly returns todo ID after creating todo. !4941
|
||||
- Better debugging for memory killer middleware. !4936
|
||||
- Remove duplicate new page btn from edit wiki. !4904
|
||||
- Use clock_gettime for all performance timestamps. !4899
|
||||
- Use memorized tags array when searching tags by name. !4859
|
||||
- Fixed avatar alignment in new MR view. !4901
|
||||
- Removed fade when filtering results. !4932
|
||||
- Fix missing avatar on system notes. !4954
|
||||
- Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973
|
||||
- Use update_columns to by_pass all the dirty code on active_record. !4985
|
||||
- Fix restore Rake task warning message output !4980
|
||||
|
||||
v 8.9.2
|
||||
- Fix visibility of snippets when searching.
|
||||
|
@ -65,6 +123,7 @@ v 8.9.1
|
|||
- Remove duplicate 'New Page' button on edit wiki page
|
||||
|
||||
v 8.9.0
|
||||
- Fix group visibility form layout in application settings
|
||||
- Fix builds API response not including commit data
|
||||
- Fix error when CI job variables key specified but not defined
|
||||
- Fix pipeline status when there are no builds in pipeline
|
||||
|
@ -160,6 +219,7 @@ v 8.9.0
|
|||
- Add Application Setting to configure Container Registry token expire delay (default 5min)
|
||||
- Cache assigned issue and merge request counts in sidebar nav
|
||||
- Use Knapsack only in CI environment
|
||||
- Updated project creation page to match new UI #2542
|
||||
- Cache project build count in sidebar nav
|
||||
- Add milestone expire date to the right sidebar
|
||||
- Manually mark a issue or merge request as a todo
|
||||
|
@ -209,12 +269,21 @@ v 8.9.0
|
|||
- Filter parameters for request_uri value on instrumented transactions.
|
||||
- Remove duplicated keys add UNIQUE index to keys fingerprint column
|
||||
- ExtractsPath get ref_names from repository cache, if not there access git.
|
||||
- Show a flash warning about the error detail of XHR requests which failed with status code 404 and 500
|
||||
- Cache user todo counts from TodoService
|
||||
- Ensure Todos counters doesn't count Todos for projects pending delete
|
||||
- Add left/right arrows horizontal navigation
|
||||
- Add tooltip to pin/unpin navbar
|
||||
- Add new sub nav style to Wiki and Graphs sub navigation
|
||||
|
||||
v 8.8.7
|
||||
- Fix privilege escalation issue with OAuth external users.
|
||||
- Ensure references to private repos aren't shown to logged-out users.
|
||||
|
||||
v 8.8.6
|
||||
- Fix visibility of snippets when searching.
|
||||
- Update omniauth-saml to 1.6.0 !4951
|
||||
|
||||
v 8.8.5
|
||||
- Import GitHub repositories respecting the API rate limit !4166
|
||||
- Fix todos page throwing errors when you have a project pending deletion !4300
|
||||
|
@ -345,6 +414,14 @@ v 8.8.0
|
|||
- When creating a .gitignore file a dropdown with templates will be provided
|
||||
- Shows the issue/MR list search/filter form and corrects the mobile styling for guest users. #17562
|
||||
|
||||
v 8.7.9
|
||||
- Fix privilege escalation issue with OAuth external users.
|
||||
- Ensure references to private repos aren't shown to logged-out users.
|
||||
|
||||
v 8.7.8
|
||||
- Fix visibility of snippets when searching.
|
||||
- Update omniauth-saml to 1.6.0 !4951
|
||||
|
||||
v 8.7.7
|
||||
- Fix import by `Any Git URL` broken if the URL contains a space
|
||||
- Prevent unauthorized access to other projects build traces
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0.0
|
||||
3.1.0
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.7.5
|
||||
0.7.7
|
||||
|
|
11
Gemfile
|
@ -91,6 +91,7 @@ gem 'fog-core', '~> 1.40'
|
|||
gem 'fog-local', '~> 0.3'
|
||||
gem 'fog-google', '~> 0.3'
|
||||
gem 'fog-openstack', '~> 0.1'
|
||||
gem 'fog-rackspace', '~> 0.1.1'
|
||||
|
||||
# for aws storage
|
||||
gem "unf", '~> 0.1.4'
|
||||
|
@ -106,7 +107,7 @@ gem 'html-pipeline', '~> 1.11.0'
|
|||
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
|
||||
gem 'github-markup', '~> 1.3.1'
|
||||
gem 'redcarpet', '~> 3.3.3'
|
||||
gem 'RedCloth', '~> 4.2.9'
|
||||
gem 'RedCloth', '~> 4.3.2'
|
||||
gem 'rdoc', '~>3.6'
|
||||
gem 'org-ruby', '~> 0.9.12'
|
||||
gem 'creole', '~> 0.5.0'
|
||||
|
@ -250,7 +251,6 @@ group :development do
|
|||
gem 'brakeman', '~> 3.3.0', require: false
|
||||
|
||||
gem 'letter_opener_web', '~> 1.3.0'
|
||||
gem 'quiet_assets', '~> 1.0.2'
|
||||
gem 'rerun', '~> 0.11.0'
|
||||
gem 'bullet', require: false
|
||||
gem 'rblineprof', platform: :mri, require: false
|
||||
|
@ -264,7 +264,7 @@ group :development do
|
|||
gem "sdoc", '~> 0.3.20'
|
||||
|
||||
# thin instead webrick
|
||||
gem 'thin', '~> 1.6.1'
|
||||
gem 'thin', '~> 1.7.0'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
|
@ -302,7 +302,6 @@ group :development, :test do
|
|||
gem 'rubocop', '~> 0.40.0', require: false
|
||||
gem 'rubocop-rspec', '~> 1.5.0', require: false
|
||||
gem 'scss_lint', '~> 0.47.0', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'simplecov', '~> 0.11.0', require: false
|
||||
gem 'flog', require: false
|
||||
gem 'flay', require: false
|
||||
|
@ -346,3 +345,7 @@ gem "paranoia", "~> 2.0"
|
|||
|
||||
# Health check
|
||||
gem 'health_check', '~> 1.5.1'
|
||||
|
||||
# System information
|
||||
gem 'vmstat', '~> 2.1.0'
|
||||
gem 'sys-filesystem', '~> 1.1.6'
|
||||
|
|
57
Gemfile.lock
|
@ -1,7 +1,7 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
RedCloth (4.2.9)
|
||||
RedCloth (4.3.2)
|
||||
ace-rails-ap (4.0.2)
|
||||
actionmailer (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
|
@ -141,12 +141,6 @@ GEM
|
|||
colorize (0.7.7)
|
||||
concurrent-ruby (1.0.2)
|
||||
connection_pool (2.2.0)
|
||||
coveralls (0.8.13)
|
||||
json (~> 1.8)
|
||||
simplecov (~> 0.11.0)
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (~> 0.19.1)
|
||||
tins (~> 1.6.0)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
creole (0.5.0)
|
||||
|
@ -243,6 +237,11 @@ GEM
|
|||
fog-core (>= 1.39)
|
||||
fog-json (>= 1.0)
|
||||
ipaddress (>= 0.8)
|
||||
fog-rackspace (0.1.1)
|
||||
fog-core (>= 1.35)
|
||||
fog-json (>= 1.0)
|
||||
fog-xml (>= 0.1)
|
||||
ipaddress (>= 0.8)
|
||||
fog-xml (0.1.2)
|
||||
fog-core
|
||||
nokogiri (~> 1.5, >= 1.5.11)
|
||||
|
@ -500,8 +499,6 @@ GEM
|
|||
pry-rails (0.3.4)
|
||||
pry (>= 0.9.10)
|
||||
pyu-ruby-sasl (0.0.3.3)
|
||||
quiet_assets (1.0.3)
|
||||
railties (>= 3.1, < 5.0)
|
||||
rack (1.6.4)
|
||||
rack-accept (0.4.5)
|
||||
rack (>= 0.4)
|
||||
|
@ -557,7 +554,7 @@ GEM
|
|||
recaptcha (3.0.0)
|
||||
json
|
||||
redcarpet (3.3.3)
|
||||
redis (3.3.0)
|
||||
redis (3.2.2)
|
||||
redis-actionpack (4.0.1)
|
||||
actionpack (~> 4)
|
||||
redis-rack (~> 1.5.0)
|
||||
|
@ -635,8 +632,8 @@ GEM
|
|||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.4.22)
|
||||
sass-rails (5.0.4)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass-rails (5.0.5)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
|
@ -650,9 +647,9 @@ GEM
|
|||
sdoc (0.3.20)
|
||||
json (>= 1.1.3)
|
||||
rdoc (~> 3.10)
|
||||
seed-fu (2.3.5)
|
||||
activerecord (>= 3.1, < 4.3)
|
||||
activesupport (>= 3.1, < 4.3)
|
||||
seed-fu (2.3.6)
|
||||
activerecord (>= 3.1)
|
||||
activesupport (>= 3.1)
|
||||
select2-rails (3.5.9.3)
|
||||
thor (~> 0.14)
|
||||
sentry-raven (1.1.0)
|
||||
|
@ -663,10 +660,11 @@ GEM
|
|||
rack
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
sidekiq (4.1.2)
|
||||
sidekiq (4.1.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
redis (~> 3.2, >= 3.2.1)
|
||||
sinatra (>= 1.4.7)
|
||||
sidekiq-cron (0.4.0)
|
||||
redis-namespace (>= 1.5.2)
|
||||
rufus-scheduler (>= 2.0.24)
|
||||
|
@ -677,8 +675,8 @@ GEM
|
|||
json (~> 1.8)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
sinatra (1.4.6)
|
||||
rack (~> 1.4)
|
||||
sinatra (1.4.7)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
six (0.2.0)
|
||||
|
@ -701,10 +699,10 @@ GEM
|
|||
spring (>= 0.9.1)
|
||||
spring-commands-teaspoon (0.0.2)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (3.6.0)
|
||||
sprockets (3.6.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.0.4)
|
||||
sprockets-rails (3.1.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
|
@ -716,6 +714,8 @@ GEM
|
|||
activerecord (>= 4.1, < 5.1)
|
||||
state_machines-activemodel (>= 0.3.0)
|
||||
stringex (2.5.2)
|
||||
sys-filesystem (1.1.6)
|
||||
ffi
|
||||
systemu (2.6.5)
|
||||
task_list (1.0.2)
|
||||
html-pipeline
|
||||
|
@ -724,14 +724,12 @@ GEM
|
|||
teaspoon-jasmine (2.2.0)
|
||||
teaspoon (>= 1.0.0)
|
||||
temple (0.7.7)
|
||||
term-ansicolor (1.3.2)
|
||||
tins (~> 1.0)
|
||||
test_after_commit (0.4.2)
|
||||
activerecord (>= 3.2)
|
||||
thin (1.6.4)
|
||||
thin (1.7.0)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (~> 1.0)
|
||||
rack (>= 1, < 3)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.5)
|
||||
|
@ -746,7 +744,6 @@ GEM
|
|||
mime-types
|
||||
multi_json (~> 1.7)
|
||||
twitter-stream (~> 0.1)
|
||||
tins (1.6.0)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
twitter-stream (0.1.16)
|
||||
|
@ -780,6 +777,7 @@ GEM
|
|||
coercible (~> 1.0)
|
||||
descendants_tracker (~> 0.0, >= 0.0.3)
|
||||
equalizer (~> 0.0, >= 0.0.9)
|
||||
vmstat (2.1.0)
|
||||
warden (1.2.6)
|
||||
rack (>= 1.0)
|
||||
web-console (2.3.0)
|
||||
|
@ -805,7 +803,7 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
RedCloth (~> 4.2.9)
|
||||
RedCloth (~> 4.3.2)
|
||||
ace-rails-ap (~> 4.0.2)
|
||||
activerecord-session_store (~> 1.0.0)
|
||||
acts-as-taggable-on (~> 3.4)
|
||||
|
@ -835,7 +833,6 @@ DEPENDENCIES
|
|||
chronic_duration (~> 0.10.6)
|
||||
coffee-rails (~> 4.1.0)
|
||||
connection_pool (~> 2.0)
|
||||
coveralls (~> 0.8.2)
|
||||
creole (~> 0.5.0)
|
||||
d3_rails (~> 3.5.0)
|
||||
database_cleaner (~> 1.4.0)
|
||||
|
@ -857,6 +854,7 @@ DEPENDENCIES
|
|||
fog-google (~> 0.3)
|
||||
fog-local (~> 0.3)
|
||||
fog-openstack (~> 0.1)
|
||||
fog-rackspace (~> 0.1.1)
|
||||
font-awesome-rails (~> 4.6.1)
|
||||
foreman
|
||||
fuubar (~> 2.0.0)
|
||||
|
@ -921,7 +919,6 @@ DEPENDENCIES
|
|||
poltergeist (~> 1.9.0)
|
||||
premailer-rails (~> 1.9.0)
|
||||
pry-rails
|
||||
quiet_assets (~> 1.0.2)
|
||||
rack-attack (~> 4.3.1)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-oauth2 (~> 1.2.1)
|
||||
|
@ -969,11 +966,12 @@ DEPENDENCIES
|
|||
spring-commands-teaspoon (~> 0.0.2)
|
||||
sprockets (~> 3.6.0)
|
||||
state_machines-activerecord (~> 0.4.0)
|
||||
sys-filesystem (~> 1.1.6)
|
||||
task_list (~> 1.0.2)
|
||||
teaspoon (~> 1.1.0)
|
||||
teaspoon-jasmine (~> 2.2.0)
|
||||
test_after_commit (~> 0.4.2)
|
||||
thin (~> 1.6.1)
|
||||
thin (~> 1.7.0)
|
||||
tinder (~> 1.10.0)
|
||||
turbolinks (~> 2.5.0)
|
||||
u2f (~> 0.2.1)
|
||||
|
@ -984,6 +982,7 @@ DEPENDENCIES
|
|||
unicorn-worker-killer (~> 0.4.2)
|
||||
version_sorter (~> 2.0.0)
|
||||
virtus (~> 1.0.1)
|
||||
vmstat (~> 2.1.0)
|
||||
web-console (~> 2.0)
|
||||
webmock (~> 1.21.0)
|
||||
wikicloth (= 0.8.1)
|
||||
|
|
Before Width: | Height: | Size: 986 B After Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 870 B |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
Before Width: | Height: | Size: 674 KiB After Width: | Height: | Size: 673 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 809 B After Width: | Height: | Size: 631 B |
Before Width: | Height: | Size: 495 B After Width: | Height: | Size: 201 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 729 B |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 621 B After Width: | Height: | Size: 621 B |
Before Width: | Height: | Size: 942 B After Width: | Height: | Size: 939 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.9 KiB |
|
@ -185,6 +185,15 @@ $ ->
|
|||
else
|
||||
buttons.enable()
|
||||
|
||||
$(document).ajaxError (e, xhrObj, xhrSetting, xhrErrorText) ->
|
||||
|
||||
if xhrObj.status is 401
|
||||
new Flash 'You need to be logged in.', 'alert'
|
||||
|
||||
else if xhrObj.status in [ 404, 500 ]
|
||||
new Flash 'Something went wrong on our end.', 'alert'
|
||||
|
||||
|
||||
# Show/Hide the profile menu when hovering the account box
|
||||
$('.account-box').hover -> $(@).toggleClass('hover')
|
||||
|
||||
|
@ -199,7 +208,6 @@ $ ->
|
|||
$('.header-content .header-logo').toggle()
|
||||
$('.header-content .navbar-collapse').toggle()
|
||||
$('.navbar-toggle').toggleClass('active')
|
||||
$('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
|
||||
|
||||
# Show/hide comments on diff
|
||||
$body.on "click", ".js-toggle-diff-comments", (e) ->
|
||||
|
@ -261,8 +269,8 @@ $ ->
|
|||
new Aside()
|
||||
|
||||
# Sidenav pinning
|
||||
if $window.width() < 1440 and $.cookie('pin_nav') is 'true'
|
||||
$.cookie('pin_nav', 'false', { path: '/' })
|
||||
if $window.width() < 1024 and $.cookie('pin_nav') is 'true'
|
||||
$.cookie('pin_nav', 'false', { path: '/', expires: 365 * 10 })
|
||||
$('.page-with-sidebar')
|
||||
.toggleClass('page-sidebar-collapsed page-sidebar-expanded')
|
||||
.removeClass('page-sidebar-pinned')
|
||||
|
@ -293,7 +301,7 @@ $ ->
|
|||
.toggleClass('header-collapsed header-expanded')
|
||||
|
||||
# Save settings
|
||||
$.cookie 'pin_nav', doPinNav, { path: '/' }
|
||||
$.cookie 'pin_nav', doPinNav, { path: '/', expires: 365 * 10 }
|
||||
|
||||
if $.cookie('pin_nav') is 'true' or doPinNav
|
||||
tooltipText = 'Unpin navigation'
|
||||
|
|
|
@ -84,6 +84,8 @@ class Dispatcher
|
|||
new Activities()
|
||||
when 'groups:show'
|
||||
shortcut_handler = new ShortcutsNavigation()
|
||||
new NotificationsForm()
|
||||
new NotificationsDropdown()
|
||||
when 'groups:group_members:index'
|
||||
new GroupMembers()
|
||||
new UsersSelect()
|
||||
|
|
|
@ -4,11 +4,19 @@ class @Flash
|
|||
@flash.html("")
|
||||
|
||||
innerDiv = $('<div/>',
|
||||
class: "flash-#{type}",
|
||||
text: message
|
||||
class: "flash-#{type}"
|
||||
)
|
||||
innerDiv.appendTo(".flash-container")
|
||||
|
||||
textDiv = $("<div/>",
|
||||
class: "flash-text",
|
||||
text: message
|
||||
)
|
||||
textDiv.appendTo(innerDiv)
|
||||
|
||||
if @flash.parent().hasClass('content-wrapper')
|
||||
textDiv.addClass('container-fluid container-limited')
|
||||
|
||||
@flash.click -> $(@).fadeOut()
|
||||
@flash.show()
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ window.GitLab ?= {}
|
|||
GitLab.GfmAutoComplete =
|
||||
dataLoading: false
|
||||
dataLoaded: false
|
||||
|
||||
cachedData: {}
|
||||
dataSource: ''
|
||||
|
||||
# Emoji
|
||||
|
@ -55,7 +55,7 @@ GitLab.GfmAutoComplete =
|
|||
@setupAtWho()
|
||||
|
||||
if @dataSource
|
||||
if !@dataLoading
|
||||
if not @dataLoading and not @cachedData
|
||||
@dataLoading = true
|
||||
|
||||
# We should wait until initializations are done
|
||||
|
@ -70,6 +70,8 @@ GitLab.GfmAutoComplete =
|
|||
@loadData(data)
|
||||
, 1000)
|
||||
|
||||
if @cachedData?
|
||||
@loadData(@cachedData)
|
||||
|
||||
setupAtWho: ->
|
||||
# Emoji
|
||||
|
@ -205,6 +207,7 @@ GitLab.GfmAutoComplete =
|
|||
$.getJSON(dataSource)
|
||||
|
||||
loadData: (data) ->
|
||||
@cachedData = data
|
||||
@dataLoaded = true
|
||||
|
||||
# load members
|
||||
|
|
|
@ -186,6 +186,8 @@ class GitLabDropdown
|
|||
@fullData = data
|
||||
|
||||
@parseData @fullData
|
||||
|
||||
@filter.input.trigger('keyup') if @options.filterable and @filter and @filter.input
|
||||
}
|
||||
|
||||
# Init filterable
|
||||
|
@ -218,6 +220,13 @@ class GitLabDropdown
|
|||
@dropdown.on 'keyup', (e) =>
|
||||
if e.which is 27 # Escape key
|
||||
$('.dropdown-menu-close', @dropdown).trigger 'click'
|
||||
@dropdown.on 'blur', 'a', (e) =>
|
||||
if e.relatedTarget?
|
||||
$relatedTarget = $(e.relatedTarget)
|
||||
$dropdownMenu = $relatedTarget.closest('.dropdown-menu')
|
||||
|
||||
if $dropdownMenu.length is 0
|
||||
@dropdown.removeClass('open')
|
||||
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
@dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) =>
|
||||
|
|
|
@ -7,13 +7,16 @@ class @ImporterStatus
|
|||
$('.js-add-to-import')
|
||||
.off 'click'
|
||||
.on 'click', (e) =>
|
||||
new_namespace = null
|
||||
$btn = $(e.currentTarget)
|
||||
$tr = $btn.closest('tr')
|
||||
$target_field = $tr.find('.import-target')
|
||||
$namespace_input = $target_field.find('input')
|
||||
id = $tr.attr('id').replace('repo_', '')
|
||||
if $tr.find('.import-target input').length > 0
|
||||
new_namespace = $tr.find('.import-target input').prop('value')
|
||||
$tr.find('.import-target').empty().append("#{new_namespace} / #{$tr.find('.import-target').data('project_name')}")
|
||||
new_namespace = null
|
||||
|
||||
if $namespace_input.length > 0
|
||||
new_namespace = $namespace_input.prop('value')
|
||||
$target_field.empty().append("#{new_namespace}/#{$target_field.data('project_name')}")
|
||||
|
||||
$btn
|
||||
.disable()
|
||||
|
|
|
@ -59,13 +59,12 @@ issuable_created = false
|
|||
filterResults: (form) =>
|
||||
formData = form.serialize()
|
||||
|
||||
$('.issues-holder, .merge-requests-holder').css('opacity', '0.5')
|
||||
formAction = form.attr('action')
|
||||
issuesUrl = formAction
|
||||
issuesUrl += ("#{if formAction.indexOf('?') < 0 then '?' else '&'}")
|
||||
issuesUrl += formData
|
||||
|
||||
Turbolinks.visit(issuesUrl);
|
||||
Turbolinks.visit(issuesUrl)
|
||||
|
||||
initChecks: ->
|
||||
@issuableBulkActions = $('.bulk-update').data('bulkActions')
|
||||
|
|
|
@ -10,17 +10,41 @@
|
|||
gl.text.selectedText = (text, textarea) ->
|
||||
text.substring(textarea.selectionStart, textarea.selectionEnd)
|
||||
|
||||
gl.text.insertText = (textArea, text, tag, selected, wrap) ->
|
||||
gl.text.lineBefore = (text, textarea) ->
|
||||
split = text.substring(0, textarea.selectionStart).trim().split('\n')
|
||||
split[split.length - 1]
|
||||
|
||||
gl.text.lineAfter = (text, textarea) ->
|
||||
text.substring(textarea.selectionEnd).trim().split('\n')[0]
|
||||
|
||||
gl.text.blockTagText = (text, textArea, blockTag, selected) ->
|
||||
lineBefore = @lineBefore(text, textArea)
|
||||
lineAfter = @lineAfter(text, textArea)
|
||||
|
||||
if lineBefore is blockTag and lineAfter is blockTag
|
||||
# To remove the block tag we have to select the line before & after
|
||||
if blockTag?
|
||||
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1)
|
||||
textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1)
|
||||
|
||||
selected
|
||||
else
|
||||
"#{blockTag}\n#{selected}\n#{blockTag}"
|
||||
|
||||
gl.text.insertText = (textArea, text, tag, blockTag, selected, wrap) ->
|
||||
selectedSplit = selected.split('\n')
|
||||
startChar = if not wrap and textArea.selectionStart > 0 then '\n' else ''
|
||||
|
||||
if selectedSplit.length > 1 and not wrap
|
||||
insertText = selectedSplit.map((val) ->
|
||||
if val.indexOf(tag) is 0
|
||||
"#{val.replace(tag, '')}"
|
||||
else
|
||||
"#{tag}#{val}"
|
||||
).join('\n')
|
||||
if selectedSplit.length > 1 and (not wrap or blockTag?)
|
||||
if blockTag?
|
||||
insertText = @blockTagText(text, textArea, blockTag, selected)
|
||||
else
|
||||
insertText = selectedSplit.map((val) ->
|
||||
if val.indexOf(tag) is 0
|
||||
"#{val.replace(tag, '')}"
|
||||
else
|
||||
"#{tag}#{val}"
|
||||
).join('\n')
|
||||
else
|
||||
insertText = "#{startChar}#{tag}#{selected}#{if wrap then tag else ' '}"
|
||||
|
||||
|
@ -51,7 +75,7 @@
|
|||
|
||||
textArea.setSelectionRange pos, pos
|
||||
|
||||
gl.text.updateText = (textArea, tag, wrap) ->
|
||||
gl.text.updateText = (textArea, tag, blockTag, wrap) ->
|
||||
$textArea = $(textArea)
|
||||
oldVal = $textArea.val()
|
||||
textArea = $textArea.get(0)
|
||||
|
@ -59,7 +83,7 @@
|
|||
selected = @selectedText(text, textArea)
|
||||
$textArea.focus()
|
||||
|
||||
@insertText(textArea, text, tag, selected, wrap)
|
||||
@insertText(textArea, text, tag, blockTag, selected, wrap)
|
||||
|
||||
gl.text.init = (form) ->
|
||||
self = @
|
||||
|
@ -70,6 +94,7 @@
|
|||
self.updateText(
|
||||
$this.closest('.md-area').find('textarea'),
|
||||
$this.data('md-tag'),
|
||||
$this.data('md-block'),
|
||||
not $this.data('md-prepend')
|
||||
)
|
||||
|
||||
|
|
|
@ -171,22 +171,15 @@ class @SearchAutocomplete
|
|||
}
|
||||
|
||||
bindEvents: ->
|
||||
$(document).on 'click', @onDocumentClick
|
||||
@searchInput.on 'keydown', @onSearchInputKeyDown
|
||||
@searchInput.on 'keyup', @onSearchInputKeyUp
|
||||
@searchInput.on 'click', @onSearchInputClick
|
||||
@searchInput.on 'focus', @onSearchInputFocus
|
||||
@searchInput.on 'blur', @onSearchInputBlur
|
||||
@clearInput.on 'click', @onClearInputClick
|
||||
@locationBadgeEl.on 'click', =>
|
||||
@searchInput.focus()
|
||||
|
||||
onDocumentClick: (e) =>
|
||||
# If clicking outside the search box
|
||||
# And search input is not focused
|
||||
# And we are not clicking inside a suggestion
|
||||
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).closest('.search-form').length
|
||||
@onSearchInputBlur()
|
||||
|
||||
enableAutocomplete: ->
|
||||
# No need to enable anything if user is not logged in
|
||||
return if !gon.current_user_id
|
||||
|
@ -287,8 +280,6 @@ class @SearchAutocomplete
|
|||
value: @originalState._location
|
||||
)
|
||||
|
||||
@dropdown.removeClass 'open'
|
||||
|
||||
badgePresent: ->
|
||||
@locationBadgeEl.length
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ class @Shortcuts
|
|||
|
||||
onToggleHelp: (e) =>
|
||||
e.preventDefault()
|
||||
@toggleHelp(@enabledHelp)
|
||||
Shortcuts.toggleHelp(@enabledHelp)
|
||||
|
||||
toggleMarkdownPreview: (e) =>
|
||||
toggleMarkdownPreview: (e) ->
|
||||
$(document).triggerHandler('markdown-preview:toggle', [e])
|
||||
|
||||
toggleHelp: (location) ->
|
||||
@toggleHelp: (location) ->
|
||||
$modal = $('#modal-shortcuts')
|
||||
|
||||
if $modal.length
|
||||
|
|
|
@ -5,9 +5,15 @@ class @TreeView
|
|||
# Code browser tree slider
|
||||
# Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
|
||||
$(".tree-content-holder .tree-item").on 'click', (e) ->
|
||||
if (e.target.nodeName != "A")
|
||||
path = $('.tree-item-file-name a', this).attr('href')
|
||||
Turbolinks.visit(path)
|
||||
$clickedEl = $(e.target)
|
||||
path = $('.tree-item-file-name a', this).attr('href')
|
||||
|
||||
if not $clickedEl.is('a') and not $clickedEl.is('.str-truncated')
|
||||
if e.metaKey or e.which is 2
|
||||
e.preventDefault()
|
||||
window.open path, '_blank'
|
||||
else
|
||||
Turbolinks.visit path
|
||||
|
||||
# Show the "Loading commit data" for only the first element
|
||||
$('span.log_loading:first').removeClass('hide')
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 10px;
|
||||
color: #4c4e54;
|
||||
font-size: 23px;
|
||||
line-height: 1.1;
|
||||
|
|
|
@ -16,4 +16,11 @@
|
|||
@extend .alert-danger;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.flash-notice, .flash-alert {
|
||||
.container-fluid.flash-text {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@
|
|||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:hover {
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $gl-link-color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.group-right-buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
font-size: 13px;
|
||||
color: $btn-placeholder-gray;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
.page-with-sidebar {
|
||||
padding-top: $header-height;
|
||||
padding-bottom: 25px;
|
||||
transition: padding $sidebar-transition-duration;
|
||||
|
||||
.sidebar-wrapper {
|
||||
|
|
|
@ -7,7 +7,7 @@ $gutter_collapsed_width: 62px;
|
|||
$gutter_width: 290px;
|
||||
$gutter_inner_width: 258px;
|
||||
$sidebar-transition-duration: .15s;
|
||||
$sidebar-breakpoint: 1440px;
|
||||
$sidebar-breakpoint: 1024px;
|
||||
|
||||
/*
|
||||
* UI elements
|
||||
|
|
|
@ -83,11 +83,7 @@
|
|||
position: relative;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
padding-left: 20px;
|
||||
|
||||
.commit-info-block {
|
||||
padding-left: 44px;
|
||||
}
|
||||
padding-left: 46px;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
|
@ -102,9 +98,7 @@
|
|||
|
||||
|
||||
.avatar {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 16px;
|
||||
margin-left: -46px;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
|
|
|
@ -41,18 +41,17 @@
|
|||
}
|
||||
|
||||
.groups-cover-block {
|
||||
|
||||
.container-fluid {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.access-request-button {
|
||||
@include btn-gray;
|
||||
.group-right-buttons {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 32px;
|
||||
padding: 3px 10px;
|
||||
text-transform: none;
|
||||
background-color: $background-color;
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
padding: 3px 10px;
|
||||
background-color: $background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,8 +264,15 @@
|
|||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
width: 49%;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-left: 0;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.commit-row-info {
|
||||
|
|
|
@ -41,6 +41,10 @@ ul.notes {
|
|||
.timeline-icon {
|
||||
.avatar {
|
||||
visibility: hidden;
|
||||
|
||||
.discussion-body & {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,53 @@
|
|||
|
||||
.new_project,
|
||||
.edit-project {
|
||||
fieldset.features {
|
||||
.control-label {
|
||||
fieldset {
|
||||
&.features .control-label {
|
||||
font-weight: normal;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
&> .form-group {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
.help-block {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.project-path {
|
||||
padding-right: 0;
|
||||
.form-control {
|
||||
border-radius: $border-radius-base;
|
||||
}
|
||||
}
|
||||
.input-group > div {
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
@media (max-width: $screen-xs-max) {
|
||||
.input-group > div {
|
||||
margin-bottom: 14px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
fieldset > .form-group:first-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
&.static-namespace {
|
||||
height: 35px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #e5e5e5;
|
||||
}
|
||||
&+ .select2 a {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,18 +266,6 @@
|
|||
@media (max-width: $screen-md-max) {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.access-request-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 61px;
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
|
@ -365,10 +396,28 @@ a.deploy-project-label {
|
|||
}
|
||||
}
|
||||
|
||||
.project-import .btn {
|
||||
float: left;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
.project-import {
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.import-buttons {
|
||||
padding-left: 0;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
.btn {
|
||||
margin-right: 10px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
&> div {
|
||||
margin-bottom: 14px;
|
||||
padding-left: 0;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-stats {
|
||||
|
|
|
@ -101,7 +101,8 @@
|
|||
margin: 0;
|
||||
|
||||
.commit {
|
||||
padding: 0 0 0 55px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
|
||||
.commit-row-title {
|
||||
.commit-row-message {
|
||||
|
|
|
@ -109,6 +109,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:metrics_packet_size,
|
||||
:send_user_confirmation_email,
|
||||
:container_registry_token_expire_delay,
|
||||
:repository_storage,
|
||||
restricted_visibility_levels: [],
|
||||
import_sources: [],
|
||||
disabled_oauth_sign_in_sources: []
|
||||
|
|
|
@ -10,6 +10,7 @@ class Admin::GroupsController < Admin::ApplicationController
|
|||
|
||||
def show
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page])
|
||||
@requesters = @group.requesters
|
||||
@projects = @group.projects.page(params[:projects_page])
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ class Admin::HooksController < Admin::ApplicationController
|
|||
redirect_to admin_hooks_path
|
||||
end
|
||||
|
||||
|
||||
def test
|
||||
@hook = SystemHook.find(params[:hook_id])
|
||||
data = {
|
||||
|
|
|
@ -20,7 +20,8 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page])
|
||||
end
|
||||
|
||||
@project_members = @project.project_members.page(params[:project_members_page])
|
||||
@project_members = @project.members.page(params[:project_members_page])
|
||||
@requesters = @project.requesters
|
||||
end
|
||||
|
||||
def transfer
|
||||
|
|
|
@ -4,8 +4,6 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
|
|||
def create
|
||||
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
|
||||
|
||||
return head(403) if @runner.is_shared? || @runner.locked?
|
||||
|
||||
runner_project = @runner.assign_to(@project, current_user)
|
||||
|
||||
if runner_project.persisted?
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
class Admin::SystemInfoController < Admin::ApplicationController
|
||||
EXCLUDED_MOUNT_OPTIONS = [
|
||||
'nobrowse',
|
||||
'read-only',
|
||||
'ro'
|
||||
]
|
||||
|
||||
EXCLUDED_MOUNT_TYPES = [
|
||||
'autofs',
|
||||
'binfmt_misc',
|
||||
'cgroup',
|
||||
'debugfs',
|
||||
'devfs',
|
||||
'devpts',
|
||||
'devtmpfs',
|
||||
'efivarfs',
|
||||
'fuse.gvfsd-fuse',
|
||||
'fuseblk',
|
||||
'fusectl',
|
||||
'hugetlbfs',
|
||||
'mqueue',
|
||||
'proc',
|
||||
'pstore',
|
||||
'securityfs',
|
||||
'sysfs',
|
||||
'tmpfs',
|
||||
'tracefs',
|
||||
'vfat'
|
||||
]
|
||||
|
||||
def show
|
||||
system_info = Vmstat.snapshot
|
||||
mounts = Sys::Filesystem.mounts
|
||||
|
||||
@disks = []
|
||||
mounts.each do |mount|
|
||||
mount_options = mount.options.split(',')
|
||||
|
||||
next if (EXCLUDED_MOUNT_OPTIONS & mount_options).any?
|
||||
next if (EXCLUDED_MOUNT_TYPES & [mount.mount_type]).any?
|
||||
|
||||
begin
|
||||
disk = Sys::Filesystem.stat(mount.mount_point)
|
||||
@disks.push({
|
||||
bytes_total: disk.bytes_total,
|
||||
bytes_used: disk.bytes_used,
|
||||
disk_name: mount.name,
|
||||
mount_path: disk.path
|
||||
})
|
||||
rescue Sys::Filesystem::Error
|
||||
end
|
||||
end
|
||||
|
||||
@cpus = system_info.cpus.length
|
||||
|
||||
@mem_used = system_info.memory.active_bytes
|
||||
@mem_total = system_info.memory.total_bytes
|
||||
end
|
||||
end
|
|
@ -25,7 +25,7 @@ module Ci
|
|||
return render_404 unless @project
|
||||
|
||||
image = Ci::ImageForBuildService.new.execute(@project, params)
|
||||
send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml"
|
||||
send_file image.path, filename: image.name, disposition: 'inline', type: "image/svg+xml"
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -10,7 +10,7 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def approve_access_request
|
||||
@member = membershipable.members.request.find(params[:id])
|
||||
@member = membershipable.requesters.find(params[:id])
|
||||
|
||||
return render_403 unless can?(current_user, action_member_permission(:update, @member), @member)
|
||||
|
||||
|
@ -20,7 +20,8 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def leave
|
||||
@member = membershipable.members.find_by(user_id: current_user)
|
||||
@member = membershipable.members.find_by(user_id: current_user) ||
|
||||
membershipable.requesters.find_by(user_id: current_user)
|
||||
Members::DestroyService.new(@member, current_user).execute
|
||||
|
||||
source_type = @member.real_source_type.humanize(capitalize: false)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class ConfirmationsController < Devise::ConfirmationsController
|
||||
|
||||
def almost_there
|
||||
flash[:notice] = nil
|
||||
render layout: "devise_empty"
|
||||
|
|
|
@ -7,7 +7,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
def index
|
||||
@project = @group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@members = @group.group_members
|
||||
@members = @members.non_pending unless can?(current_user, :admin_group, @group)
|
||||
@members = @members.non_invite unless can?(current_user, :admin_group, @group)
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
|
@ -15,6 +15,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
@members = @members.order('access_level DESC').page(params[:page]).per(50)
|
||||
@requesters = @group.requesters if can?(current_user, :admin_group, @group)
|
||||
|
||||
@group_member = @group.group_members.new
|
||||
end
|
||||
|
@ -34,7 +35,8 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@group_member = @group.group_members.find(params[:id])
|
||||
@group_member = @group.members.find_by(id: params[:id]) ||
|
||||
@group.requesters.find_by(id: params[:id])
|
||||
|
||||
Members::DestroyService.new(@group_member, current_user).execute
|
||||
|
||||
|
|
|
@ -37,15 +37,12 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@last_push = current_user.recent_push if current_user
|
||||
if current_user
|
||||
@last_push = current_user.recent_push
|
||||
@notification_setting = current_user.notification_settings_for(group)
|
||||
end
|
||||
|
||||
@projects = @projects.includes(:namespace)
|
||||
@projects = @projects.sorted_by_activity
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.page(params[:page]) if params[:filter_projects].blank?
|
||||
|
||||
@shared_projects = GroupProjectsFinder.new(group, only_shared: true).execute(current_user)
|
||||
setup_projects
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
@ -97,6 +94,16 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def setup_projects
|
||||
@projects = @projects.includes(:namespace)
|
||||
@projects = @projects.sorted_by_activity
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.page(params[:page]) if params[:filter_projects].blank?
|
||||
|
||||
@shared_projects = GroupProjectsFinder.new(group, only_shared: true).execute(current_user)
|
||||
end
|
||||
|
||||
def authorize_create_group!
|
||||
unless can?(current_user, :create_group, nil)
|
||||
return render_404
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class Import::BaseController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def get_or_create_namespace
|
||||
|
|
|
@ -5,7 +5,6 @@ class Import::FogbugzController < Import::BaseController
|
|||
rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized
|
||||
|
||||
def new
|
||||
|
||||
end
|
||||
|
||||
def callback
|
||||
|
@ -22,7 +21,6 @@ class Import::FogbugzController < Import::BaseController
|
|||
end
|
||||
|
||||
def new_user_map
|
||||
|
||||
end
|
||||
|
||||
def create_user_map
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
class Import::GithubController < Import::BaseController
|
||||
before_action :verify_github_import_enabled
|
||||
before_action :github_auth, except: :callback
|
||||
before_action :github_auth, only: [:status, :jobs, :create]
|
||||
|
||||
rescue_from Octokit::Unauthorized, with: :github_unauthorized
|
||||
|
||||
helper_method :logged_in_with_github?
|
||||
|
||||
def new
|
||||
if logged_in_with_github?
|
||||
go_to_github_for_permissions
|
||||
elsif session[:github_access_token]
|
||||
redirect_to status_import_github_url
|
||||
end
|
||||
end
|
||||
|
||||
def callback
|
||||
session[:github_access_token] = client.get_token(params[:code])
|
||||
redirect_to status_import_github_url
|
||||
end
|
||||
|
||||
def personal_access_token
|
||||
session[:github_access_token] = params[:personal_access_token]
|
||||
redirect_to status_import_github_url
|
||||
end
|
||||
|
||||
def status
|
||||
@repos = client.repos
|
||||
@already_added_projects = current_user.created_projects.where(import_type: "github")
|
||||
|
@ -57,10 +72,14 @@ class Import::GithubController < Import::BaseController
|
|||
end
|
||||
|
||||
def github_unauthorized
|
||||
go_to_github_for_permissions
|
||||
session[:github_access_token] = nil
|
||||
redirect_to new_import_github_url,
|
||||
alert: 'Access denied to your GitHub account.'
|
||||
end
|
||||
|
||||
private
|
||||
def logged_in_with_github?
|
||||
current_user.identities.exists?(provider: 'github')
|
||||
end
|
||||
|
||||
def access_params
|
||||
{ github_access_token: session[:github_access_token] }
|
||||
|
|
|
@ -44,5 +44,4 @@ class Import::GitoriousController < Import::BaseController
|
|||
def verify_gitorious_import_enabled
|
||||
render_404 unless gitorious_import_enabled?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@ class Import::GoogleCodeController < Import::BaseController
|
|||
before_action :user_map, only: [:new_user_map, :create_user_map]
|
||||
|
||||
def new
|
||||
|
||||
end
|
||||
|
||||
def callback
|
||||
|
@ -34,7 +33,6 @@ class Import::GoogleCodeController < Import::BaseController
|
|||
end
|
||||
|
||||
def new_user_map
|
||||
|
||||
end
|
||||
|
||||
def create_user_map
|
||||
|
|
|
@ -5,7 +5,6 @@ class InvitesController < ApplicationController
|
|||
respond_to :html
|
||||
|
||||
def show
|
||||
|
||||
end
|
||||
|
||||
def accept
|
||||
|
|
|
@ -2,11 +2,9 @@ class NotificationSettingsController < ApplicationController
|
|||
before_action :authenticate_user!
|
||||
|
||||
def create
|
||||
project = Project.find(params[:project][:id])
|
||||
return render_404 unless can_read?(resource)
|
||||
|
||||
return render_404 unless can?(current_user, :read_project, project)
|
||||
|
||||
@notification_setting = current_user.notification_settings_for(project)
|
||||
@notification_setting = current_user.notification_settings_for(resource)
|
||||
@saved = @notification_setting.update_attributes(notification_setting_params)
|
||||
|
||||
render_response
|
||||
|
@ -21,6 +19,22 @@ class NotificationSettingsController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def resource
|
||||
@resource ||=
|
||||
if params[:project_id].present?
|
||||
Project.find(params[:project_id])
|
||||
elsif params[:namespace_id].present?
|
||||
Group.find(params[:namespace_id])
|
||||
end
|
||||
end
|
||||
|
||||
def can_read?(resource)
|
||||
ability_name = resource.class.name.downcase
|
||||
ability_name = "read_#{ability_name}".to_sym
|
||||
|
||||
can?(current_user, ability_name, resource)
|
||||
end
|
||||
|
||||
def render_response
|
||||
render json: {
|
||||
html: view_to_html_string("shared/notifications/_button", notification_setting: @notification_setting),
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
# This file should be identical in GitLab Community Edition and Enterprise Edition
|
||||
|
||||
class Projects::GitHttpController < Projects::ApplicationController
|
||||
include ActionController::HttpAuthentication::Basic
|
||||
include KerberosSpnegoHelper
|
||||
|
||||
attr_reader :user
|
||||
|
||||
# Git clients will not know what authenticity token to send along
|
||||
|
@ -40,9 +45,12 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def authenticate_user
|
||||
return if project && project.public? && upload_pack?
|
||||
if project && project.public? && upload_pack?
|
||||
return # Allow access
|
||||
end
|
||||
|
||||
authenticate_or_request_with_http_basic do |login, password|
|
||||
if allow_basic_auth? && basic_auth_provided?
|
||||
login, password = user_name_and_password(request)
|
||||
auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
|
||||
|
||||
if auth_result.type == :ci && upload_pack?
|
||||
|
@ -53,8 +61,31 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
@user = auth_result.user
|
||||
end
|
||||
|
||||
ci? || user
|
||||
if ci? || user
|
||||
return # Allow access
|
||||
end
|
||||
elsif allow_kerberos_spnego_auth? && spnego_provided?
|
||||
@user = find_kerberos_user
|
||||
|
||||
if user
|
||||
send_final_spnego_response
|
||||
return # Allow access
|
||||
end
|
||||
end
|
||||
|
||||
send_challenges
|
||||
render plain: "HTTP Basic: Access denied\n", status: 401
|
||||
end
|
||||
|
||||
def basic_auth_provided?
|
||||
has_basic_credentials?(request)
|
||||
end
|
||||
|
||||
def send_challenges
|
||||
challenges = []
|
||||
challenges << 'Basic realm="GitLab"' if allow_basic_auth?
|
||||
challenges << spnego_challenge if allow_kerberos_spnego_auth?
|
||||
headers['Www-Authenticate'] = challenges.join("\n") if challenges.any?
|
||||
end
|
||||
|
||||
def ensure_project_found!
|
||||
|
@ -120,7 +151,7 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def render_not_found
|
||||
render text: 'Not Found', status: :not_found
|
||||
render plain: 'Not Found', status: :not_found
|
||||
end
|
||||
|
||||
def ci?
|
||||
|
|
|
@ -76,7 +76,6 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
render json: @issue.to_json(include: [:milestone, :labels])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -59,7 +59,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render json: @merge_request }
|
||||
format.patch { render text: @merge_request.to_patch }
|
||||
format.patch do
|
||||
headers.store(*Gitlab::Workhorse.send_git_patch(@project.repository,
|
||||
@merge_request.diff_base_commit.id,
|
||||
@merge_request.last_commit.id))
|
||||
headers['Content-Disposition'] = 'inline'
|
||||
head :ok
|
||||
end
|
||||
format.diff do
|
||||
return render_404 unless @merge_request.diff_refs
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ class Projects::NetworkController < Projects::ApplicationController
|
|||
before_action :authorize_download_code!
|
||||
|
||||
def show
|
||||
|
||||
@url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))
|
||||
@commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
|
||||
def index
|
||||
@project_members = @project.project_members
|
||||
@project_members = @project_members.non_pending unless can?(current_user, :admin_project, @project)
|
||||
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
|
||||
|
||||
if params[:search].present?
|
||||
users = @project.users.search(params[:search]).to_a
|
||||
|
@ -19,7 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
|
||||
if @group
|
||||
@group_members = @group.group_members
|
||||
@group_members = @group_members.non_pending unless can?(current_user, :admin_group, @group)
|
||||
@group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group)
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
|
@ -29,6 +29,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
@group_members = @group_members.order('access_level DESC')
|
||||
end
|
||||
|
||||
@requesters = @project.requesters if can?(current_user, :admin_project, @project)
|
||||
|
||||
@project_member = @project.project_members.new
|
||||
@project_group_links = @project.project_group_links
|
||||
end
|
||||
|
@ -48,7 +50,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@project_member = @project.project_members.find(params[:id])
|
||||
@project_member = @project.members.find_by(id: params[:id]) ||
|
||||
@project.requesters.find_by(id: params[:id])
|
||||
|
||||
Members::DestroyService.new(@project_member, current_user).execute
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
|
|||
def create
|
||||
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
|
||||
|
||||
return head(403) if @runner.is_shared? || @runner.locked?
|
||||
return head(403) unless current_user.ci_authorized_runners.include?(@runner)
|
||||
return head(403) unless can?(current_user, :assign_runner, @runner)
|
||||
|
||||
path = runners_path(project)
|
||||
runner_project = @runner.assign_to(project, current_user)
|
||||
|
|
|
@ -54,7 +54,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
@note = @project.notes.new(noteable: @snippet)
|
||||
@notes = @snippet.notes.fresh
|
||||
@notes = Banzai::NoteRenderer.render(@snippet.notes.fresh, @project, current_user)
|
||||
@noteable = @snippet
|
||||
end
|
||||
|
||||
|
|
|
@ -124,5 +124,4 @@ class Projects::WikisController < Projects::ApplicationController
|
|||
def wiki_params
|
||||
params[:wiki].slice(:title, :content, :format, :message)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -4,7 +4,8 @@ class ProjectsController < Projects::ApplicationController
|
|||
before_action :authenticate_user!, except: [:show, :activity, :refs]
|
||||
before_action :project, except: [:new, :create]
|
||||
before_action :repository, except: [:new, :create]
|
||||
before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists?
|
||||
before_action :assign_ref_vars, only: [:show], if: :repo_exists?
|
||||
before_action :tree, only: [:show], if: :project_view_files?
|
||||
|
||||
# Authorize
|
||||
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
|
||||
|
@ -303,6 +304,10 @@ class ProjectsController < Projects::ApplicationController
|
|||
project.repository_exists? && !project.empty_repo?
|
||||
end
|
||||
|
||||
def project_view_files?
|
||||
current_user && current_user.project_view == 'files'
|
||||
end
|
||||
|
||||
# Override extract_ref from ExtractsPath, which returns the branch and file path
|
||||
# for the blob/tree, which in this case is just the root of the default branch.
|
||||
# This way we avoid to access the repository.ref_names.
|
||||
|
|
|
@ -29,10 +29,10 @@ class PipelinesFinder
|
|||
end
|
||||
|
||||
def branches
|
||||
project.repository.branches.map(&:name)
|
||||
project.repository.branch_names
|
||||
end
|
||||
|
||||
def tags
|
||||
project.repository.tags.map(&:name)
|
||||
project.repository.tag_names
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,7 @@ class TodosFinder
|
|||
def execute
|
||||
items = current_user.todos
|
||||
items = by_action_id(items)
|
||||
items = by_action(items)
|
||||
items = by_author(items)
|
||||
items = by_project(items)
|
||||
items = by_state(items)
|
||||
|
@ -43,6 +44,18 @@ class TodosFinder
|
|||
params[:action_id]
|
||||
end
|
||||
|
||||
def to_action_id
|
||||
Todo::ACTION_NAMES.key(action.to_sym)
|
||||
end
|
||||
|
||||
def action?
|
||||
action.present? && to_action_id
|
||||
end
|
||||
|
||||
def action
|
||||
params[:action]
|
||||
end
|
||||
|
||||
def author?
|
||||
params[:author_id].present?
|
||||
end
|
||||
|
@ -96,6 +109,14 @@ class TodosFinder
|
|||
params[:type]
|
||||
end
|
||||
|
||||
def by_action(items)
|
||||
if action?
|
||||
items = items.where(action: to_action_id)
|
||||
end
|
||||
|
||||
items
|
||||
end
|
||||
|
||||
def by_action_id(items)
|
||||
if action_id?
|
||||
items = items.where(action: action_id)
|
||||
|
|
|
@ -78,4 +78,12 @@ module ApplicationSettingsHelper
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def repository_storage_options_for_select
|
||||
options = Gitlab.config.repositories.storages.map do |name, path|
|
||||
["#{name} - #{path}", name]
|
||||
end
|
||||
|
||||
options_for_select(options, @application_setting.repository_storage)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
module BlobHelper
|
||||
def highlighter(blob_name, blob_content, nowrap: false)
|
||||
Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap)
|
||||
def highlighter(blob_name, blob_content, repository: nil, nowrap: false)
|
||||
Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap, repository: repository)
|
||||
end
|
||||
|
||||
def highlight(blob_name, blob_content, nowrap: false, plain: false)
|
||||
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain)
|
||||
def highlight(blob_name, blob_content, repository: nil, nowrap: false, plain: false)
|
||||
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain, repository: repository)
|
||||
end
|
||||
|
||||
def no_highlight_files
|
||||
|
|
|
@ -69,7 +69,7 @@ module DropdownsHelper
|
|||
|
||||
def dropdown_filter(placeholder, search_id: nil)
|
||||
content_tag :div, class: "dropdown-input" do
|
||||
filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder
|
||||
filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
|
||||
filter_output << icon('search', class: "dropdown-input-search")
|
||||
filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
module EmailsHelper
|
||||
|
||||
# Google Actions
|
||||
# https://developers.google.com/gmail/markup/reference/go-to-action
|
||||
def email_action(url)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
module IssuablesHelper
|
||||
|
||||
def sidebar_gutter_toggle_icon
|
||||
sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right')
|
||||
end
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
module KerberosSpnegoHelper
|
||||
def allow_basic_auth?
|
||||
true # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
|
||||
def allow_kerberos_spnego_auth?
|
||||
false # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
end
|
|
@ -34,10 +34,7 @@ module LabelsHelper
|
|||
# Returns a String
|
||||
def link_to_label(label, project: nil, type: :issue, tooltip: true, css_class: nil, &block)
|
||||
project ||= @project || label.project
|
||||
link = send("namespace_project_#{type.to_s.pluralize}_path",
|
||||
project.namespace,
|
||||
project,
|
||||
label_name: [label.name])
|
||||
link = label_filter_path(project, label, type: type)
|
||||
|
||||
if block_given?
|
||||
link_to link, class: css_class, &block
|
||||
|
@ -46,6 +43,13 @@ module LabelsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def label_filter_path(project, label, type: issue)
|
||||
send("namespace_project_#{type.to_s.pluralize}_path",
|
||||
project.namespace,
|
||||
project,
|
||||
label_name: [label.name])
|
||||
end
|
||||
|
||||
def project_label_names
|
||||
@project.labels.pluck(:title)
|
||||
end
|
||||
|
|
|
@ -12,6 +12,17 @@ module MembersHelper
|
|||
can?(current_user, action_member_permission(:admin, member), member.source)
|
||||
end
|
||||
|
||||
def can_see_request_access_button?(source)
|
||||
source_parent = source.respond_to?(:group) && source.group
|
||||
|
||||
return false if source_parent && source.group.members.exists?(user_id: current_user.id)
|
||||
return false if source_parent && source.group.requesters.exists?(user_id: current_user.id)
|
||||
return false if source.members.exists?(user_id: current_user.id)
|
||||
return true if source.requesters.exists?(user_id: current_user.id)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def remove_member_message(member, user: nil)
|
||||
user = current_user if defined?(current_user)
|
||||
|
||||
|
|
|
@ -69,4 +69,14 @@ module NotesHelper
|
|||
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
|
||||
data: data, title: 'Add a reply'
|
||||
end
|
||||
|
||||
def note_max_access_for_user(note)
|
||||
@max_access_by_user_id ||= Hash.new do |hash, key|
|
||||
project = key[:project]
|
||||
hash[key] = project.team.human_max_access(key[:user_id])
|
||||
end
|
||||
|
||||
full_key = { project: note.project, user_id: note.author_id }
|
||||
@max_access_by_user_id[full_key]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -72,6 +72,6 @@ module NotificationsHelper
|
|||
# Create hidden field to send notification setting source to controller
|
||||
def hidden_setting_source_input(notification_setting)
|
||||
return unless notification_setting.source_type
|
||||
hidden_field_tag "#{notification_setting.source_type.downcase}[id]", notification_setting.source_id
|
||||
hidden_field_tag "#{notification_setting.source_type.downcase}_id", notification_setting.source_id
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,7 +52,7 @@ module PageLayoutHelper
|
|||
raise ArgumentError, 'cannot provide more than two attributes' if map.length > 2
|
||||
|
||||
@page_card_attributes ||= {}
|
||||
@page_card_attributes = map.reject { |_,v| v.blank? } if map.present?
|
||||
@page_card_attributes = map.reject { |_, v| v.blank? } if map.present?
|
||||
@page_card_attributes
|
||||
end
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ module ProjectsHelper
|
|||
def link_to_member_avatar(author, opts = {})
|
||||
default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" }
|
||||
opts = default_opts.merge(opts)
|
||||
image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
|
||||
image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt: '') if opts[:avatar]
|
||||
end
|
||||
|
||||
def link_to_member(project, author, opts = {}, &block)
|
||||
|
@ -27,7 +27,7 @@ module ProjectsHelper
|
|||
author_html = ""
|
||||
|
||||
# Build avatar image tag
|
||||
author_html << image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
|
||||
author_html << image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt: '') if opts[:avatar]
|
||||
|
||||
# Build name span tag
|
||||
if opts[:by_username]
|
||||
|
@ -327,9 +327,9 @@ module ProjectsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def sanitize_repo_path(message)
|
||||
def sanitize_repo_path(project, message)
|
||||
return '' unless message.present?
|
||||
|
||||
message.strip.gsub(Gitlab.config.gitlab_shell.repos_path.chomp('/'), "[REPOS PATH]")
|
||||
message.strip.gsub(project.repository_storage_path.chomp('/'), "[REPOS PATH]")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
module SearchHelper
|
||||
|
||||
def search_autocomplete_opts(term)
|
||||
return unless current_user
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Ability
|
||||
class << self
|
||||
# rubocop: disable Metrics/CyclomaticComplexity
|
||||
def allowed(user, subject)
|
||||
return anonymous_abilities(user, subject) if user.nil?
|
||||
return [] unless user.is_a?(User)
|
||||
|
@ -19,6 +20,7 @@ class Ability
|
|||
when ProjectMember then project_member_abilities(user, subject)
|
||||
when User then user_abilities
|
||||
when ExternalIssue, Deployment, Environment then project_abilities(user, subject.project)
|
||||
when Ci::Runner then runner_abilities(user, subject)
|
||||
else []
|
||||
end.concat(global_abilities(user))
|
||||
end
|
||||
|
@ -512,6 +514,18 @@ class Ability
|
|||
rules
|
||||
end
|
||||
|
||||
def runner_abilities(user, runner)
|
||||
if user.is_admin?
|
||||
[:assign_runner]
|
||||
elsif runner.is_shared? || runner.locked?
|
||||
[]
|
||||
elsif user.ci_authorized_runners.include?(runner)
|
||||
[:assign_runner]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def user_abilities
|
||||
[:read_user]
|
||||
end
|
||||
|
|
|
@ -55,6 +55,10 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
presence: true,
|
||||
numericality: { only_integer: true, greater_than: 0 }
|
||||
|
||||
validates :repository_storage,
|
||||
presence: true,
|
||||
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
|
||||
|
||||
validates_each :restricted_visibility_levels do |record, attr, value|
|
||||
unless value.nil?
|
||||
value.each do |level|
|
||||
|
@ -134,6 +138,7 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
disabled_oauth_sign_in_sources: [],
|
||||
send_user_confirmation_email: false,
|
||||
container_registry_token_expire_delay: 5,
|
||||
repository_storage: 'default',
|
||||
)
|
||||
end
|
||||
|
||||
|
|