mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-19 09:36:47 +10:00
Merge branch 'upstream/6-2-stable' of /home/git/repositories/gitlab/gitlab-ee
This commit is contained in:
@@ -20,6 +20,7 @@ Vagrantfile
|
||||
config/gitlab.yml
|
||||
config/database.yml
|
||||
config/initializers/omniauth.rb
|
||||
config/initializers/rack_attack.rb
|
||||
config/unicorn.rb
|
||||
config/resque.yml
|
||||
config/aws.yml
|
||||
|
||||
+1
-5
@@ -8,7 +8,6 @@ branches:
|
||||
only:
|
||||
- 'master'
|
||||
rvm:
|
||||
- 1.9.3-p392
|
||||
- 2.0.0
|
||||
services:
|
||||
- mysql
|
||||
@@ -16,7 +15,4 @@ services:
|
||||
before_script:
|
||||
- "cp config/database.yml.$DB config/database.yml"
|
||||
- "cp config/gitlab.yml.example config/gitlab.yml"
|
||||
- "bundle exec rake db:setup RAILS_ENV=test"
|
||||
- "bundle exec rake db:seed_fu RAILS_ENV=test"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
script: "bundle exec rake travis --trace"
|
||||
script: "bundle exec rake gitlab:test --trace"
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
v 6.2.0
|
||||
- Public project pages are now visible to everyone (files, issues, wik, etc.)
|
||||
THIS MEANS YOUR ISSUES AND WIKI FOR PUBLIC PROJECTS ARE PUBLICLY VISIBLE AFTER THE UPGRADE
|
||||
- Add group access to permissions page
|
||||
- Require current password to change one
|
||||
- Group owner or admin can remove other group owners
|
||||
- Remove group transfer since we have multiple owners
|
||||
- Respect authorization in Repository API
|
||||
- Improve UI for Project#files page
|
||||
- Add more security specs
|
||||
- Added search for projects by name to api (Izaak Alpert)
|
||||
- Make default user theme configurable (Izaak Alpert)
|
||||
- Update logic for validates_merge_request for tree of MR (Andrew Kumanyaev)
|
||||
- Rake tasks for web hooks management (Jonhnny Weslley)
|
||||
- Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
|
||||
- API: Remove group
|
||||
- API: Remove project
|
||||
- Avatar upload on profile page with a maximum of 200KB (Steven Thonus)
|
||||
- Store the sessions in Redis instead of the cookie store
|
||||
- Fixed relative links in markdown
|
||||
- User must confirm his email if signup enabled
|
||||
- User must confirm changed email
|
||||
|
||||
v 6.1.0
|
||||
- Project specific IDs for issues, mr, milestones
|
||||
Above items will get a new id and for example all bookmarked issue urls will change.
|
||||
|
||||
@@ -16,6 +16,7 @@ gem "pg", group: :postgres
|
||||
|
||||
# Auth
|
||||
gem "devise", '~> 2.2'
|
||||
gem "devise-async"
|
||||
gem 'omniauth', "~> 1.1.3"
|
||||
gem 'omniauth-google-oauth2'
|
||||
gem 'omniauth-twitter'
|
||||
@@ -23,7 +24,7 @@ gem 'omniauth-github'
|
||||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '2.3.1'
|
||||
gem "gitlab_git", "~> 3.0.0.rc2"
|
||||
|
||||
# Ruby/Rack Git Smart-HTTP Server Handler
|
||||
gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
|
||||
@@ -112,6 +113,9 @@ gem 'tinder', '~> 1.9.2'
|
||||
# HipChat integration
|
||||
gem "hipchat", "~> 0.9.0"
|
||||
|
||||
# Flowdock integration
|
||||
gem "gitlab-flowdock-git-hook", "~> 0.4.2"
|
||||
|
||||
# d3
|
||||
gem "d3_rails", "~> 3.1.4"
|
||||
|
||||
@@ -121,6 +125,9 @@ gem "underscore-rails", "~> 1.4.4"
|
||||
# Sanitize user input
|
||||
gem "sanitize"
|
||||
|
||||
# Protect against bruteforcing
|
||||
gem "rack-attack"
|
||||
|
||||
group :assets do
|
||||
gem "sass-rails"
|
||||
gem "coffee-rails"
|
||||
@@ -143,10 +150,11 @@ group :assets do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem "annotate", git: "https://github.com/ctran/annotate_models.git"
|
||||
gem "annotate", "~> 2.6.0.beta2"
|
||||
gem "letter_opener"
|
||||
gem 'quiet_assets', '~> 1.0.1'
|
||||
gem 'rack-mini-profiler'
|
||||
|
||||
# Better errors handler
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
|
||||
+38
-28
@@ -1,11 +1,3 @@
|
||||
GIT
|
||||
remote: https://github.com/ctran/annotate_models.git
|
||||
revision: 18a4e2eb77c8f3ef695b563e4a7ca45dfede819b
|
||||
specs:
|
||||
annotate (2.6.0.beta2)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
@@ -39,17 +31,20 @@ GEM
|
||||
acts-as-taggable-on (2.4.1)
|
||||
rails (>= 3, < 5)
|
||||
addressable (2.3.4)
|
||||
annotate (2.6.0.beta2)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
arel (3.0.2)
|
||||
asciidoctor (0.1.3)
|
||||
awesome_print (1.1.0)
|
||||
awesome_print (1.2.0)
|
||||
backports (3.3.2)
|
||||
bcrypt-ruby (3.1.1)
|
||||
better_errors (0.9.0)
|
||||
better_errors (1.0.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
binding_of_caller (0.7.2)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootstrap-sass (2.3.2.0)
|
||||
bootstrap-sass (2.3.2.2)
|
||||
sass (~> 3.2)
|
||||
builder (3.0.4)
|
||||
capybara (2.1.0)
|
||||
@@ -73,7 +68,7 @@ GEM
|
||||
sass-rails (>= 3.2)
|
||||
chunky_png (1.2.8)
|
||||
cliver (0.2.1)
|
||||
code_analyzer (0.3.2)
|
||||
code_analyzer (0.4.3)
|
||||
sexp_processor
|
||||
coderay (1.0.9)
|
||||
coffee-rails (3.2.2)
|
||||
@@ -92,11 +87,11 @@ GEM
|
||||
compass-rails (1.0.3)
|
||||
compass (>= 0.12.2, < 0.14)
|
||||
connection_pool (1.1.0)
|
||||
coveralls (0.6.7)
|
||||
colorize
|
||||
coveralls (0.7.0)
|
||||
multi_json (~> 1.3)
|
||||
rest-client
|
||||
simplecov (>= 0.7)
|
||||
term-ansicolor
|
||||
thor
|
||||
crack (0.4.0)
|
||||
safe_yaml (~> 0.9.0)
|
||||
@@ -111,6 +106,8 @@ GEM
|
||||
orm_adapter (~> 0.1)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.2.1)
|
||||
devise-async (0.8.0)
|
||||
devise (>= 2.2, < 3.2)
|
||||
diff-lcs (1.2.4)
|
||||
dotenv (0.8.0)
|
||||
email_spec (1.4.0)
|
||||
@@ -133,7 +130,7 @@ GEM
|
||||
multipart-post (~> 1.1)
|
||||
faraday_middleware (0.9.0)
|
||||
faraday (>= 0.7.4, < 0.9)
|
||||
ffaker (1.16.1)
|
||||
ffaker (1.18.0)
|
||||
ffi (1.9.0)
|
||||
fog (1.3.1)
|
||||
builder
|
||||
@@ -145,7 +142,7 @@ GEM
|
||||
net-ssh (>= 2.1.3)
|
||||
nokogiri (~> 1.5.0)
|
||||
ruby-hmac
|
||||
font-awesome-rails (3.2.1.2)
|
||||
font-awesome-rails (3.2.1.3)
|
||||
railties (>= 3.2, < 5.0)
|
||||
foreman (0.63.0)
|
||||
dotenv (>= 0.7)
|
||||
@@ -161,6 +158,9 @@ GEM
|
||||
pygments.rb (>= 0.2.13)
|
||||
github-markdown (0.5.3)
|
||||
github-markup (0.7.5)
|
||||
gitlab-flowdock-git-hook (0.4.2.2)
|
||||
gitlab-grit (>= 2.4.1)
|
||||
multi_json
|
||||
gitlab-gollum-lib (1.0.1)
|
||||
github-markdown (~> 0.5.3)
|
||||
github-markup (>= 0.7.5, < 1.0.0)
|
||||
@@ -171,7 +171,7 @@ GEM
|
||||
stringex (~> 1.5.1)
|
||||
gitlab-grack (1.0.1)
|
||||
rack (~> 1.4.1)
|
||||
gitlab-grit (2.6.0)
|
||||
gitlab-grit (2.6.1)
|
||||
charlock_holmes (~> 0.6.9)
|
||||
diff-lcs (~> 1.1)
|
||||
mime-types (~> 1.15)
|
||||
@@ -179,10 +179,10 @@ GEM
|
||||
gitlab-pygments.rb (0.3.2)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
gitlab_git (2.3.1)
|
||||
gitlab_git (3.0.0.rc2)
|
||||
activesupport (~> 3.2.13)
|
||||
github-linguist (~> 2.3.4)
|
||||
gitlab-grit (~> 2.6.0)
|
||||
gitlab-grit (~> 2.6.1)
|
||||
gitlab_meta (6.0)
|
||||
gitlab_omniauth-ldap (1.0.3)
|
||||
net-ldap (~> 0.3.1)
|
||||
@@ -278,7 +278,7 @@ GEM
|
||||
minitest (4.7.4)
|
||||
modernizr (2.6.2)
|
||||
sprockets (~> 2.0)
|
||||
multi_json (1.7.9)
|
||||
multi_json (1.8.0)
|
||||
multi_xml (0.5.4)
|
||||
multipart-post (1.2.0)
|
||||
mysql2 (0.3.11)
|
||||
@@ -334,9 +334,11 @@ GEM
|
||||
rack (1.4.5)
|
||||
rack-accept (0.4.5)
|
||||
rack (>= 0.4)
|
||||
rack-attack (2.2.1)
|
||||
rack
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-mini-profiler (0.1.26)
|
||||
rack-mini-profiler (0.1.31)
|
||||
rack (>= 1.1.3)
|
||||
rack-mount (0.8.3)
|
||||
rack (>= 1.0.0)
|
||||
@@ -357,13 +359,14 @@ GEM
|
||||
rails-dev-tweaks (0.6.1)
|
||||
actionpack (~> 3.1)
|
||||
railties (~> 3.1)
|
||||
rails_best_practices (1.13.8)
|
||||
rails_best_practices (1.14.4)
|
||||
activesupport
|
||||
awesome_print
|
||||
code_analyzer
|
||||
code_analyzer (>= 0.4.3)
|
||||
colored
|
||||
erubis
|
||||
i18n
|
||||
require_all
|
||||
ruby-progressbar
|
||||
railties (3.2.13)
|
||||
actionpack (= 3.2.13)
|
||||
@@ -403,6 +406,7 @@ GEM
|
||||
redis-store (1.1.4)
|
||||
redis (>= 2.2)
|
||||
ref (1.0.5)
|
||||
require_all (1.3.1)
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
rspec (2.13.0)
|
||||
@@ -427,7 +431,7 @@ GEM
|
||||
safe_yaml (0.9.3)
|
||||
sanitize (2.0.3)
|
||||
nokogiri (>= 1.4.4, < 1.6)
|
||||
sass (3.2.9)
|
||||
sass (3.2.11)
|
||||
sass-rails (3.2.6)
|
||||
railties (~> 3.2.0)
|
||||
sass (>= 3.1.10)
|
||||
@@ -447,7 +451,7 @@ GEM
|
||||
rubyzip
|
||||
websocket (~> 1.0.4)
|
||||
settingslogic (2.0.9)
|
||||
sexp_processor (4.2.1)
|
||||
sexp_processor (4.3.0)
|
||||
shoulda-matchers (2.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
sidekiq (2.14.0)
|
||||
@@ -487,7 +491,9 @@ GEM
|
||||
state_machine (1.2.0)
|
||||
stringex (1.5.1)
|
||||
temple (0.6.5)
|
||||
test_after_commit (0.2.0)
|
||||
term-ansicolor (1.2.2)
|
||||
tins (~> 0.8)
|
||||
test_after_commit (0.2.1)
|
||||
therubyracer (0.11.4)
|
||||
libv8 (~> 3.11.8.12)
|
||||
ref
|
||||
@@ -507,6 +513,7 @@ GEM
|
||||
mime-types (~> 1.19)
|
||||
multi_json (~> 1.5)
|
||||
twitter-stream (~> 0.1)
|
||||
tins (0.11.0)
|
||||
treetop (1.4.14)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
@@ -544,7 +551,7 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
acts-as-taggable-on
|
||||
annotate!
|
||||
annotate (~> 2.6.0.beta2)
|
||||
asciidoctor
|
||||
awesome_print
|
||||
better_errors
|
||||
@@ -559,6 +566,7 @@ DEPENDENCIES
|
||||
d3_rails (~> 3.1.4)
|
||||
database_cleaner
|
||||
devise (~> 2.2)
|
||||
devise-async
|
||||
email_spec
|
||||
enumerize
|
||||
factory_girl_rails
|
||||
@@ -569,10 +577,11 @@ DEPENDENCIES
|
||||
gemoji (~> 1.2.1)
|
||||
github-linguist
|
||||
github-markup (~> 0.7.4)
|
||||
gitlab-flowdock-git-hook (~> 0.4.2)
|
||||
gitlab-gollum-lib (~> 1.0.1)
|
||||
gitlab-grack (~> 1.0.1)
|
||||
gitlab-pygments.rb (~> 0.3.2)
|
||||
gitlab_git (= 2.3.1)
|
||||
gitlab_git (~> 3.0.0.rc2)
|
||||
gitlab_meta (= 6.0)
|
||||
gitlab_omniauth-ldap (= 1.0.3)
|
||||
gon
|
||||
@@ -604,6 +613,7 @@ DEPENDENCIES
|
||||
poltergeist (~> 1.4.1)
|
||||
pry
|
||||
quiet_assets (~> 1.0.1)
|
||||
rack-attack
|
||||
rack-mini-profiler
|
||||
rails (= 3.2.13)
|
||||
rails-dev-tweaks
|
||||
|
||||
@@ -127,14 +127,17 @@ or start each component separately
|
||||
|
||||
### GitLab interfaces
|
||||
|
||||
* [GitLab API](doc/api/README.md)
|
||||
* [GitLab API doc](doc/api/README.md) or see the [GitLab API website](http://api.gitlab.org/)
|
||||
|
||||
* [Rake tasks](doc/raketasks)
|
||||
* [Rake tasks](doc/raketasks) including a [backup and restore procedure](doc/raketasks/backup_restore.md)
|
||||
|
||||
* [Directory structure](doc/install/structure.md)
|
||||
|
||||
* [Databases](doc/install/databases.md)
|
||||
* [Database installation](doc/install/databases.md)
|
||||
|
||||
* [Markdown specification](doc/markdown/markdown.md)
|
||||
|
||||
* [Security guide](doc/security/rack_attack.md) to throttle abusive requests
|
||||
|
||||
### Getting help
|
||||
|
||||
@@ -157,10 +160,8 @@ or start each component separately
|
||||
|
||||
### Getting in touch
|
||||
|
||||
* [Core team](https://github.com/gitlabhq?tab=members)
|
||||
* [Core team](http://gitlab.org/team/)
|
||||
|
||||
* [Contributors](https://github.com/gitlabhq/gitlabhq/graphs/contributors)
|
||||
* [Contributors](http://contributors.gitlab.org/)
|
||||
|
||||
* [Leader](https://github.com/randx)
|
||||
|
||||
* [Contact page](http://gitlab.org/contact/)
|
||||
* [Community](http://gitlab.org/community/)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
@@ -16,3 +16,13 @@ $ ->
|
||||
|
||||
$('.update-notifications').on 'ajax:complete', ->
|
||||
$(this).find('.btn-save').enableButton()
|
||||
|
||||
|
||||
$('.js-choose-user-avatar-button').bind "click", ->
|
||||
form = $(this).closest("form")
|
||||
form.find(".js-user-avatar-input").click()
|
||||
|
||||
$('.js-user-avatar-input').bind "change", ->
|
||||
form = $(this).closest("form")
|
||||
filename = $(this).val().replace(/^.*[\\\/]/, '')
|
||||
form.find(".js-avatar-filename").text(filename)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
$ ->
|
||||
userFormatResult = (user) ->
|
||||
avatar = gon.gravatar_url
|
||||
avatar = avatar.replace('%{hash}', md5(user.email))
|
||||
avatar = avatar.replace('%{size}', '24')
|
||||
|
||||
if user.avatar
|
||||
avatar = user.avatar.url
|
||||
else
|
||||
avatar = gon.gravatar_url
|
||||
avatar = avatar.replace('%{hash}', md5(user.email))
|
||||
avatar = avatar.replace('%{size}', '24')
|
||||
markup = "<div class='user-result'>"
|
||||
markup += "<div class='user-image'><img class='avatar s24' src='" + avatar + "'></div>"
|
||||
markup += "<div class='user-name'>" + user.name + "</div>"
|
||||
|
||||
@@ -140,27 +140,6 @@ p.time {
|
||||
border-bottom: 2px solid #F90;
|
||||
}
|
||||
|
||||
.status_info {
|
||||
font-size: 14px;
|
||||
padding: 5px 15px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
@include border-radius(4px);
|
||||
|
||||
&.success {
|
||||
background: #4A4;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&.error {
|
||||
background: #DA4E49;
|
||||
color: #FFF;
|
||||
}
|
||||
}
|
||||
|
||||
.thin_area{
|
||||
height: 150px;
|
||||
}
|
||||
@@ -270,27 +249,6 @@ li.note {
|
||||
}
|
||||
}
|
||||
|
||||
.oauth_select_holder {
|
||||
padding: 20px;
|
||||
img {
|
||||
padding: 5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.active {
|
||||
img {
|
||||
border: 1px solid #ccc;
|
||||
background: $hover;
|
||||
@include border-radius(5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-build-token {
|
||||
float: left;
|
||||
padding: 6px 20px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.gitlab-promo {
|
||||
a {
|
||||
color: #aaa;
|
||||
@@ -386,3 +344,8 @@ table {
|
||||
width: 50px;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
|
||||
@extend .btn-new;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,5 @@ $baseLineHeight: 18px !default;
|
||||
@import "gitlab_bootstrap/buttons.scss";
|
||||
@import "gitlab_bootstrap/blocks.scss";
|
||||
@import "gitlab_bootstrap/files.scss";
|
||||
@import "gitlab_bootstrap/tables.scss";
|
||||
@import "gitlab_bootstrap/lists.scss";
|
||||
@import "gitlab_bootstrap/forms.scss";
|
||||
|
||||
@@ -19,4 +19,5 @@
|
||||
&.s32 { width: 32px; height: 32px; margin-right: 10px; }
|
||||
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
|
||||
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
|
||||
&.s160 { width: 160px; height: 160px; margin-right: 20px; }
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
.ui-box {
|
||||
background: #FFF;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #CCC;
|
||||
border: 1px solid #DDD;
|
||||
word-wrap: break-word;
|
||||
|
||||
&.small-box {
|
||||
@@ -32,8 +32,12 @@
|
||||
}
|
||||
|
||||
&.ui-box-show {
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
color: #666;
|
||||
margin:20px 0;
|
||||
background: #FFF;
|
||||
box-shadow: inset 0 1px 0 #fff, 0 1px 5px #f1f1f1;
|
||||
@include linear-gradient(#fafafa, #f1f1f1);
|
||||
|
||||
.control-group {
|
||||
margin-bottom: 0;
|
||||
@@ -69,7 +73,6 @@
|
||||
|
||||
.ui-box-head {
|
||||
.box-title {
|
||||
color: $style_color;
|
||||
font-size: 18px;
|
||||
font-weight: normal;
|
||||
line-height: 28px;
|
||||
|
||||
@@ -87,3 +87,25 @@ pre.well-pre {
|
||||
font-weight: bold;
|
||||
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
|
||||
}
|
||||
|
||||
/** Big Labels **/
|
||||
.state-label {
|
||||
font-size: 14px;
|
||||
padding: 5px 15px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
position: relative;
|
||||
top: -5px;
|
||||
@include border-radius(4px);
|
||||
text-shadow: none;
|
||||
|
||||
&.state-label-green {
|
||||
background: #4A4;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
&.state-label-red {
|
||||
background: #DA4E49;
|
||||
color: #FFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
border: 1px solid #CCC;
|
||||
margin-bottom: 1em;
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
}
|
||||
|
||||
.file-title {
|
||||
border-bottom: 1px solid #bbb;
|
||||
@include bg-dark-gray-gradient;
|
||||
@@ -65,6 +69,12 @@
|
||||
|
||||
}
|
||||
|
||||
&.blob-no-preview {
|
||||
background: #eee;
|
||||
text-shadow: 0 1px 2px #FFF;
|
||||
padding: 100px 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame file
|
||||
*/
|
||||
|
||||
@@ -95,6 +95,14 @@
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
th {
|
||||
background: #EEE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin page-title {
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-striped;
|
||||
border: 1px solid #CCC;
|
||||
width: 100%;
|
||||
|
||||
&.low {
|
||||
td {
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&.headless {
|
||||
tr:first-child td{
|
||||
border-top: 1px solid #CCC;
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #CCC;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
@include bg-dark-gray-gradient;
|
||||
|
||||
ul.nav {
|
||||
text-shadow: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 10px;
|
||||
line-height: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
border-color: #f1f1f1;
|
||||
line-height: 28px;
|
||||
|
||||
.s16 {
|
||||
margin-top: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-left: 1px solid #CCC;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: 1px solid #CCC;
|
||||
}
|
||||
}
|
||||
|
||||
&.bordered {
|
||||
@extend .table-bordered;
|
||||
}
|
||||
|
||||
&.lite {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
tr, td {
|
||||
border: none;
|
||||
background:none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,7 @@
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
font-family: $monospace_font;
|
||||
border: none;
|
||||
margin: 0px;
|
||||
@@ -418,7 +419,6 @@
|
||||
.commit-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.commit-description {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
a {
|
||||
border-color: #CCC !important;
|
||||
border-color: #DDD !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,12 +85,18 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.last-activity, .owner-info {
|
||||
.last-activity {
|
||||
color: #AAA;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
.date, .owner {
|
||||
.date {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group-row {
|
||||
.arrow {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
border-bottom: 1px solid #eee;
|
||||
.event-title {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
.author_name {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* Login Page */
|
||||
body.login-page{
|
||||
background: #474D57;
|
||||
.container .content { padding-top: 4%; }
|
||||
.container > .content {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-box{
|
||||
|
||||
@@ -135,11 +135,15 @@ ul.notes {
|
||||
background-color: $white;
|
||||
border-width: 1px 0;
|
||||
padding-top: 0;
|
||||
|
||||
li {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.reply-btn {
|
||||
margin-top: 8px;
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,3 +4,41 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.account-page {
|
||||
fieldset {
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px dashed #ddd;
|
||||
padding-bottom: 15px;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
legend {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oauth_select_holder {
|
||||
img {
|
||||
padding: 2px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.active {
|
||||
img {
|
||||
border: 1px solid #4BD;
|
||||
background: $hover;
|
||||
@include border-radius(5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-build-token {
|
||||
float: left;
|
||||
padding: 6px 20px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,21 +79,6 @@ ul.nav.nav-projects-tabs {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.public-projects {
|
||||
li {
|
||||
.project-title {
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-left: 15px;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-projects {
|
||||
li {
|
||||
.project-title {
|
||||
@@ -110,7 +95,6 @@ ul.nav.nav-projects-tabs {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.public-clone {
|
||||
background: #333;
|
||||
color: #f5f5f5;
|
||||
@@ -123,3 +107,11 @@ ul.nav.nav-projects-tabs {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.public-projects .repo-info {
|
||||
color: #777;
|
||||
|
||||
a {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,21 @@
|
||||
}
|
||||
|
||||
.tree-table {
|
||||
@extend .table;
|
||||
@include border-radius(0);
|
||||
.tree-item {
|
||||
td {
|
||||
|
||||
tr {
|
||||
td, th {
|
||||
padding: 8px 10px;
|
||||
strong {
|
||||
font-weight: normal;
|
||||
}
|
||||
line-height: 20px;
|
||||
}
|
||||
th {
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid #CCC;
|
||||
}
|
||||
td {
|
||||
border-color: #F1F1F1;
|
||||
}
|
||||
&:hover {
|
||||
td {
|
||||
@@ -29,12 +37,11 @@
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
td {
|
||||
background: $hover;
|
||||
border-top: 1px solid #ADF;
|
||||
border-bottom: 1px solid #ADF;
|
||||
background: #f5f5f5;
|
||||
border-top: 1px solid #EEE;
|
||||
border-bottom: 1px solid #EEE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,24 +63,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tree-table {
|
||||
th .btn {
|
||||
margin: -2px -1px;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
td {
|
||||
line-height: 20px;
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
|
||||
.tree_author {
|
||||
padding-right: 8px;
|
||||
|
||||
img.avatar {
|
||||
margin-top: 0;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.tree_commit {
|
||||
|
||||
@@ -13,7 +13,7 @@ class SearchContext
|
||||
projects = Project.where(id: project_ids)
|
||||
result[:projects] = projects.search(query).limit(20)
|
||||
|
||||
# Search inside singe project
|
||||
# Search inside single project
|
||||
project = projects.first if projects.length == 1
|
||||
|
||||
if params[:search_code].present?
|
||||
|
||||
@@ -20,9 +20,9 @@ class Admin::GroupsController < Admin::ApplicationController
|
||||
def create
|
||||
@group = Group.new(params[:group])
|
||||
@group.path = @group.name.dup.parameterize if @group.name
|
||||
@group.owner = current_user
|
||||
|
||||
if @group.save
|
||||
@group.add_owner(current_user)
|
||||
redirect_to [:admin, @group], notice: 'Group was successfully created.'
|
||||
else
|
||||
render "new"
|
||||
@@ -30,14 +30,7 @@ class Admin::GroupsController < Admin::ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
group_params = params[:group].dup
|
||||
owner_id =group_params.delete(:owner_id)
|
||||
|
||||
if owner_id
|
||||
@group.change_owner(User.find(owner_id))
|
||||
end
|
||||
|
||||
if @group.update_attributes(group_params)
|
||||
if @group.update_attributes(params[:group])
|
||||
redirect_to [:admin, @group], notice: 'Group was successfully updated.'
|
||||
else
|
||||
render "edit"
|
||||
|
||||
@@ -47,6 +47,8 @@ class Admin::UsersController < Admin::ApplicationController
|
||||
@user = User.build_user(params[:user].merge(opts), as: :admin)
|
||||
@user.admin = (admin && admin.to_i > 0)
|
||||
@user.created_by_id = current_user.id
|
||||
@user.generate_password
|
||||
@user.confirm!
|
||||
|
||||
respond_to do |format|
|
||||
if @user.save
|
||||
@@ -71,6 +73,7 @@ class Admin::UsersController < Admin::ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
if user.update_attributes(params[:user], as: :admin)
|
||||
user.confirm!
|
||||
format.html { redirect_to [:admin, user], notice: 'User was successfully updated.' }
|
||||
format.json { head :ok }
|
||||
else
|
||||
|
||||
@@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
|
||||
before_filter :authenticate_user!
|
||||
before_filter :reject_blocked!
|
||||
before_filter :check_password_expiration
|
||||
before_filter :set_current_user_for_thread
|
||||
around_filter :set_current_user_for_thread
|
||||
before_filter :add_abilities
|
||||
before_filter :ldap_security_check
|
||||
before_filter :dev_tools if Rails.env == 'development'
|
||||
@@ -51,6 +51,11 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def set_current_user_for_thread
|
||||
Thread.current[:current_user] = current_user
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
Thread.current[:current_user] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def abilities
|
||||
@@ -64,6 +69,15 @@ class ApplicationController < ActionController::Base
|
||||
def project
|
||||
id = params[:project_id] || params[:id]
|
||||
|
||||
# Redirect from
|
||||
# localhost/group/project.git
|
||||
# to
|
||||
# localhost/group/project
|
||||
#
|
||||
if id =~ /\.git\Z/
|
||||
redirect_to request.original_url.gsub(/\.git\Z/, '') and return
|
||||
end
|
||||
|
||||
@project = Project.find_with_namespace(id)
|
||||
|
||||
if @project and can?(current_user, :read_project, @project)
|
||||
|
||||
@@ -5,10 +5,14 @@ class DashboardController < ApplicationController
|
||||
before_filter :event_filter, only: :show
|
||||
|
||||
def show
|
||||
# Fetch only 30 projects.
|
||||
# If user needs more - point to Dashboard#projects page
|
||||
@projects_limit = 30
|
||||
|
||||
@groups = current_user.authorized_groups.sort_by(&:human_name)
|
||||
@has_authorized_projects = @projects.count > 0
|
||||
@projects_count = @projects.count
|
||||
@projects = @projects.limit(20)
|
||||
@projects = @projects.limit(@projects_limit)
|
||||
|
||||
@events = Event.in_projects(current_user.authorized_projects.pluck(:id))
|
||||
@events = @event_filter.apply_filter(@events)
|
||||
|
||||
@@ -21,9 +21,9 @@ class GroupsController < ApplicationController
|
||||
def create
|
||||
@group = Group.new(params[:group])
|
||||
@group.path = @group.name.dup.parameterize if @group.name
|
||||
@group.owner = current_user
|
||||
|
||||
if @group.save
|
||||
@group.add_owner(current_user)
|
||||
redirect_to @group, notice: 'Group was successfully created.'
|
||||
else
|
||||
render action: "new"
|
||||
@@ -75,15 +75,7 @@ class GroupsController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
group_params = params[:group].dup
|
||||
owner_id = group_params.delete(:owner_id)
|
||||
|
||||
if owner_id
|
||||
@group.owner = User.find(owner_id)
|
||||
@group.save
|
||||
end
|
||||
|
||||
if @group.update_attributes(group_params)
|
||||
if @group.update_attributes(params[:group])
|
||||
redirect_to @group, notice: 'Group was successfully updated.'
|
||||
else
|
||||
render action: "edit"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Profiles::AccountsController < ApplicationController
|
||||
layout "profile"
|
||||
|
||||
def show
|
||||
@user = current_user
|
||||
end
|
||||
end
|
||||
@@ -8,8 +8,8 @@ class Profiles::GroupsController < ApplicationController
|
||||
def leave
|
||||
@users_group = group.users_groups.where(user_id: current_user.id).first
|
||||
|
||||
if group.owner == current_user
|
||||
redirect_to(profile_groups_path, alert: "You can't leave group. You must transfer it to another owner before leaving.")
|
||||
if group.last_owner?(current_user)
|
||||
redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.")
|
||||
else
|
||||
@users_group.destroy
|
||||
redirect_to(profile_groups_path, info: "You left #{group.name} group.")
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class Profiles::PasswordsController < ApplicationController
|
||||
layout 'navless'
|
||||
layout :determine_layout
|
||||
|
||||
skip_before_filter :check_password_expiration
|
||||
skip_before_filter :check_password_expiration, only: [:new, :create]
|
||||
|
||||
before_filter :set_user
|
||||
before_filter :set_title
|
||||
before_filter :authorize_change_password!
|
||||
|
||||
def new
|
||||
end
|
||||
@@ -26,6 +27,32 @@ class Profiles::PasswordsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
password_attributes = params[:user].select do |key, value|
|
||||
%w(password password_confirmation).include?(key.to_s)
|
||||
end
|
||||
|
||||
unless @user.valid_password?(params[:user][:current_password])
|
||||
redirect_to edit_profile_password_path, alert: 'You must provide a valid current password'
|
||||
return
|
||||
end
|
||||
|
||||
if @user.update_attributes(password_attributes)
|
||||
flash[:notice] = "Password was successfully updated. Please login with it"
|
||||
redirect_to new_user_session_path
|
||||
else
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def reset
|
||||
current_user.send_reset_password_instructions
|
||||
redirect_to edit_profile_password_path, notice: 'We sent you an email with reset password instructions'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@@ -35,4 +62,16 @@ class Profiles::PasswordsController < ApplicationController
|
||||
def set_title
|
||||
@title = "New password"
|
||||
end
|
||||
|
||||
def determine_layout
|
||||
if [:new, :create].include?(action_name.to_sym)
|
||||
'navless'
|
||||
else
|
||||
'profile'
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_change_password!
|
||||
return render_404 if @user.ldap_user?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@ class ProfilesController < ApplicationController
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
|
||||
before_filter :user
|
||||
before_filter :authorize_change_password!, only: :update_password
|
||||
before_filter :authorize_change_username!, only: :update_username
|
||||
|
||||
layout 'profile'
|
||||
@@ -13,9 +12,6 @@ class ProfilesController < ApplicationController
|
||||
def design
|
||||
end
|
||||
|
||||
def account
|
||||
end
|
||||
|
||||
def update
|
||||
if @user.update_attributes(params[:user])
|
||||
flash[:notice] = "Profile was successfully updated"
|
||||
@@ -29,26 +25,12 @@ class ProfilesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def token
|
||||
end
|
||||
|
||||
def update_password
|
||||
params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
|
||||
|
||||
if @user.update_attributes(params[:user])
|
||||
flash[:notice] = "Password was successfully updated. Please login with it"
|
||||
redirect_to new_user_session_path
|
||||
else
|
||||
render 'account'
|
||||
end
|
||||
end
|
||||
|
||||
def reset_private_token
|
||||
if current_user.reset_authentication_token!
|
||||
flash[:notice] = "Token was successfully updated"
|
||||
end
|
||||
|
||||
redirect_to account_profile_path
|
||||
redirect_to profile_account_path
|
||||
end
|
||||
|
||||
def history
|
||||
@@ -69,10 +51,6 @@ class ProfilesController < ApplicationController
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
def authorize_change_password!
|
||||
return render_404 if @user.ldap_user?
|
||||
end
|
||||
|
||||
def authorize_change_username!
|
||||
return render_404 unless @user.can_change_username?
|
||||
end
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
class Projects::ApplicationController < ApplicationController
|
||||
before_filter :project
|
||||
before_filter :repository
|
||||
layout 'projects'
|
||||
layout :determine_layout
|
||||
|
||||
def authenticate_user!
|
||||
# Restrict access to Projects area only
|
||||
# for non-signed users
|
||||
if !current_user
|
||||
id = params[:project_id] || params[:id]
|
||||
@project = Project.find_with_namespace(id)
|
||||
|
||||
return if @project && @project.public
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def determine_layout
|
||||
if current_user
|
||||
'projects'
|
||||
else
|
||||
'public_projects'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Projects::BlameController < Projects::ApplicationController
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
def show
|
||||
@blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
@blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ class Projects::BlobController < Projects::ApplicationController
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
def show
|
||||
@blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
|
||||
not_found! unless @blob
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ class Projects::EditTreeController < Projects::ApplicationController
|
||||
before_filter :edit_requirements, only: [:show, :update]
|
||||
|
||||
def show
|
||||
@last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, @ref, @path).sha
|
||||
@last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -32,9 +32,9 @@ class Projects::EditTreeController < Projects::ApplicationController
|
||||
private
|
||||
|
||||
def edit_requirements
|
||||
@blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
|
||||
unless @blob.exists? && @blob.text?
|
||||
unless @blob
|
||||
redirect_to project_blob_path(@project, @id), notice: "You can only edit text files"
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
class Projects::HooksController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_filter :authorize_read_project!
|
||||
before_filter :authorize_admin_project!, only: [:new, :create, :destroy]
|
||||
before_filter :authorize_admin_project!
|
||||
|
||||
respond_to :html
|
||||
|
||||
|
||||
@@ -157,12 +157,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
end
|
||||
|
||||
def validates_merge_request
|
||||
# Show git not found page if target branch doesn't exist
|
||||
return invalid_mr unless @merge_request.target_project.repository.branch_names.include?(@merge_request.target_branch)
|
||||
# Show git not found page
|
||||
# if there is no saved commits between source & target branch
|
||||
if @merge_request.commits.blank?
|
||||
# and if source target doesn't exist
|
||||
return invalid_mr unless @merge_request.target_project.repository.branch_names.include?(@merge_request.target_branch)
|
||||
|
||||
# Show git not found page if source branch doesn't exist
|
||||
# and there is no saved commits between source & target branch
|
||||
return invalid_mr if !@merge_request.source_project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank?
|
||||
# or if source branch doesn't exist
|
||||
return invalid_mr unless @merge_request.source_project.repository.branch_names.include?(@merge_request.source_branch)
|
||||
end
|
||||
end
|
||||
|
||||
def define_show_vars
|
||||
|
||||
@@ -14,7 +14,7 @@ class Projects::MilestonesController < Projects::ApplicationController
|
||||
@milestones = case params[:f]
|
||||
when 'all'; @project.milestones.order("state, due_date DESC")
|
||||
when 'closed'; @project.milestones.closed.order("due_date DESC")
|
||||
else @project.milestones.active.order("due_date DESC")
|
||||
else @project.milestones.active.order("due_date ASC")
|
||||
end
|
||||
|
||||
@milestones = @milestones.includes(:project)
|
||||
|
||||
@@ -8,9 +8,9 @@ class Projects::RawController < Projects::ApplicationController
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
def show
|
||||
@blob = Gitlab::Git::Blob.new(@repository, @commit.id, @ref, @path)
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
|
||||
if @blob.exists?
|
||||
if @blob
|
||||
type = if @blob.mime_type =~ /html|javascript/
|
||||
'text/plain; charset=utf-8'
|
||||
else
|
||||
|
||||
@@ -24,13 +24,14 @@ class Projects::RefsController < Projects::ApplicationController
|
||||
format.js do
|
||||
@ref = params[:ref]
|
||||
define_tree_vars
|
||||
tree
|
||||
render "tree"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def logs_tree
|
||||
contents = @tree.entries
|
||||
contents = tree.entries
|
||||
@logs = contents.map do |content|
|
||||
file = params[:path] ? File.join(params[:path], content.name) : content.name
|
||||
last_commit = @repo.commits(@commit.id, file, 1).last
|
||||
|
||||
@@ -14,8 +14,6 @@ class Projects::SnippetsController < Projects::ApplicationController
|
||||
# Allow destroy snippet
|
||||
before_filter :authorize_admin_project_snippet!, only: [:destroy]
|
||||
|
||||
layout 'projects'
|
||||
|
||||
respond_to :html
|
||||
|
||||
def index
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
class Projects::TeamMembersController < Projects::ApplicationController
|
||||
# Authorize
|
||||
before_filter :authorize_read_project!
|
||||
before_filter :authorize_admin_project!, except: [:index, :show]
|
||||
before_filter :authorize_admin_project!
|
||||
|
||||
layout "project_settings"
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ class Projects::TreeController < Projects::ApplicationController
|
||||
before_filter :require_non_empty_project
|
||||
|
||||
def show
|
||||
return not_found! if tree.entries.empty?
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
# Disable cache so browser history works
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class ProjectsController < Projects::ApplicationController
|
||||
skip_before_filter :project, only: [:new, :create]
|
||||
skip_before_filter :repository, only: [:new, :create]
|
||||
class ProjectsController < ApplicationController
|
||||
skip_before_filter :authenticate_user!, only: [:show]
|
||||
before_filter :project, except: [:new, :create]
|
||||
before_filter :repository, except: [:new, :create]
|
||||
|
||||
# Authorize
|
||||
before_filter :authorize_read_project!, except: [:index, :new, :create]
|
||||
@@ -54,8 +55,9 @@ class ProjectsController < Projects::ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
limit = (params[:limit] || 20).to_i
|
||||
return authenticate_user! unless @project.public || current_user
|
||||
|
||||
limit = (params[:limit] || 20).to_i
|
||||
@events = @project.events.recent
|
||||
@events = event_filter.apply_filter(@events)
|
||||
@events = @events.limit(limit).offset(params[:offset] || 0)
|
||||
@@ -67,10 +69,12 @@ class ProjectsController < Projects::ApplicationController
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @project.empty_repo?
|
||||
render "projects/empty"
|
||||
render "projects/empty", layout: user_layout
|
||||
else
|
||||
@last_push = current_user.recent_push(@project.id)
|
||||
render :show
|
||||
if current_user
|
||||
@last_push = current_user.recent_push(@project.id)
|
||||
end
|
||||
render :show, layout: user_layout
|
||||
end
|
||||
end
|
||||
format.js
|
||||
@@ -121,4 +125,8 @@ class ProjectsController < Projects::ApplicationController
|
||||
def set_title
|
||||
@title = 'New Project'
|
||||
end
|
||||
|
||||
def user_layout
|
||||
current_user ? "projects" : "public_projects"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Public::ProjectsController < ApplicationController
|
||||
skip_before_filter :authenticate_user!,
|
||||
:reject_blocked, :set_current_user_for_observers,
|
||||
:add_abilities
|
||||
:reject_blocked, :set_current_user_for_observers,
|
||||
:add_abilities
|
||||
|
||||
layout 'public'
|
||||
|
||||
@@ -10,15 +10,4 @@ class Public::ProjectsController < ApplicationController
|
||||
@projects = @projects.search(params[:search]) if params[:search].present?
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
|
||||
end
|
||||
|
||||
def show
|
||||
@project = Project.public_only.find_with_namespace(params[:id])
|
||||
render_404 and return unless @project
|
||||
|
||||
@repository = @project.repository
|
||||
@recent_tags = @repository.tags.first(10)
|
||||
|
||||
@commit = @repository.commit(params[:ref])
|
||||
@tree = Tree.new(@repository, @commit.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,7 +19,7 @@ class UsersGroupsController < ApplicationController
|
||||
|
||||
def destroy
|
||||
@users_group = @group.users_groups.find(params[:id])
|
||||
@users_group.destroy unless @users_group.user == @group.owner
|
||||
@users_group.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' }
|
||||
|
||||
@@ -49,6 +49,15 @@ module ApplicationHelper
|
||||
args.any? { |v| v.to_s.downcase == action_name }
|
||||
end
|
||||
|
||||
def avatar_icon(user_email = '', size = nil)
|
||||
user = User.find_by_email(user_email)
|
||||
if user && user.avatar.present?
|
||||
user.avatar.url
|
||||
else
|
||||
gravatar_icon(user_email, size)
|
||||
end
|
||||
end
|
||||
|
||||
def gravatar_icon(user_email = '', size = nil)
|
||||
size = 40 if size.nil? || size <= 0
|
||||
|
||||
@@ -89,49 +98,6 @@ module ApplicationHelper
|
||||
grouped_options_for_select(options, @ref || @project.default_branch)
|
||||
end
|
||||
|
||||
def search_autocomplete_source
|
||||
projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
|
||||
groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
|
||||
|
||||
default_nav = [
|
||||
{ label: "My Profile", url: profile_path },
|
||||
{ label: "My SSH Keys", url: profile_keys_path },
|
||||
{ label: "My Dashboard", url: root_path },
|
||||
{ label: "Admin Section", url: admin_root_path },
|
||||
]
|
||||
|
||||
help_nav = [
|
||||
{ label: "help: API Help", url: help_api_path },
|
||||
{ label: "help: Markdown Help", url: help_markdown_path },
|
||||
{ label: "help: Permissions Help", url: help_permissions_path },
|
||||
{ label: "help: Public Access Help", url: help_public_access_path },
|
||||
{ label: "help: Rake Tasks Help", url: help_raketasks_path },
|
||||
{ label: "help: SSH Keys Help", url: help_ssh_path },
|
||||
{ label: "help: System Hooks Help", url: help_system_hooks_path },
|
||||
{ label: "help: Web Hooks Help", url: help_web_hooks_path },
|
||||
{ label: "help: Workflow Help", url: help_workflow_path },
|
||||
]
|
||||
|
||||
project_nav = []
|
||||
if @project && @project.repository.exists? && @project.repository.root_ref
|
||||
project_nav = [
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Files", url: project_tree_path(@project, @ref || @project.repository.root_ref) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Commits", url: project_commits_path(@project, @ref || @project.repository.root_ref) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Network", url: project_network_path(@project, @ref || @project.repository.root_ref) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Graph", url: project_graph_path(@project, @ref || @project.repository.root_ref) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Issues", url: project_issues_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Merge Requests", url: project_merge_requests_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Milestones", url: project_milestones_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Snippets", url: project_snippets_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Team", url: project_team_index_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Wall", url: project_wall_path(@project) },
|
||||
{ label: "#{simple_sanitize(@project.name_with_namespace)} - Wiki", url: project_wikis_path(@project) },
|
||||
]
|
||||
end
|
||||
|
||||
[groups, projects, default_nav, project_nav, help_nav].flatten.to_json
|
||||
end
|
||||
|
||||
def emoji_autocomplete_source
|
||||
# should be an array of strings
|
||||
# so to_s can be called, because it is sufficient and to_json is too slow
|
||||
@@ -181,7 +147,7 @@ module ApplicationHelper
|
||||
alt: "Sign in with #{provider.to_s.titleize}")
|
||||
end
|
||||
|
||||
def simple_sanitize str
|
||||
def simple_sanitize(str)
|
||||
sanitize(str, tags: %w(a span))
|
||||
end
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ module CommitsHelper
|
||||
source_name = commit.send "#{options[:source]}_name".to_sym
|
||||
source_email = commit.send "#{options[:source]}_email".to_sym
|
||||
text = if options[:avatar]
|
||||
avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
|
||||
avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
|
||||
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
|
||||
else
|
||||
source_name
|
||||
|
||||
@@ -34,7 +34,8 @@ module GitlabMarkdownHelper
|
||||
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
|
||||
filter_html: true,
|
||||
with_toc_data: true,
|
||||
hard_wrap: true)
|
||||
hard_wrap: true,
|
||||
safe_links_only: true)
|
||||
@markdown = Redcarpet::Markdown.new(gitlab_renderer,
|
||||
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
|
||||
no_intra_emphasis: true,
|
||||
@@ -57,4 +58,104 @@ module GitlabMarkdownHelper
|
||||
wiki_page.formatted_content.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
# text - whole text from a markdown file
|
||||
# project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq
|
||||
# ref - name of the branch or reference, eg. stable
|
||||
# requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from
|
||||
# wiki - whether the markdown is from wiki or not
|
||||
def create_relative_links(text, project_path_with_namespace, ref, requested_path, wiki = false)
|
||||
paths = extract_paths(text)
|
||||
paths.each do |file_path|
|
||||
new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref)
|
||||
# Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word
|
||||
# e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test
|
||||
text.gsub!("](#{file_path})", "](/#{new_path})")
|
||||
end
|
||||
text
|
||||
end
|
||||
|
||||
def extract_paths(markdown_text)
|
||||
all_markdown_paths = pick_out_paths(markdown_text)
|
||||
paths = remove_empty(all_markdown_paths)
|
||||
select_relative(paths)
|
||||
end
|
||||
|
||||
# Split the markdown text to each line and find all paths, this will match anything with - ]("some_text")
|
||||
def pick_out_paths(markdown_text)
|
||||
markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) }
|
||||
end
|
||||
|
||||
# Removes any empty result produced by not matching the regexp
|
||||
def remove_empty(paths)
|
||||
paths.reject{|l| l.empty? }.flatten
|
||||
end
|
||||
|
||||
# Reject any path that contains ignored protocol
|
||||
# eg. reject "https://gitlab.org} but accept "doc/api/README.md"
|
||||
def select_relative(paths)
|
||||
paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?}
|
||||
end
|
||||
|
||||
def ignored_protocols
|
||||
["http://","https://", "ftp://", "mailto:"]
|
||||
end
|
||||
|
||||
def rebuild_path(path_with_namespace, path, requested_path, ref)
|
||||
file_path = relative_file_path(path, requested_path)
|
||||
[
|
||||
path_with_namespace,
|
||||
path_with_ref(file_path, ref),
|
||||
file_path
|
||||
].compact.join("/")
|
||||
end
|
||||
|
||||
# Checks if the path exists in the repo
|
||||
# eg. checks if doc/README.md exists, if it doesn't then it is a wiki link
|
||||
def path_with_ref(path, ref)
|
||||
if file_exists?(path)
|
||||
"#{local_path(path)}/#{correct_ref(ref)}"
|
||||
else
|
||||
"wikis"
|
||||
end
|
||||
end
|
||||
|
||||
def relative_file_path(path, requested_path)
|
||||
nested_path = build_nested_path(path, requested_path)
|
||||
return nested_path if file_exists?(nested_path)
|
||||
path
|
||||
end
|
||||
|
||||
# Covering a special case, when the link is referencing file in the same directory eg:
|
||||
# If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md)
|
||||
# this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md
|
||||
# If we are at doc/api and the README.md shown in below the tree view
|
||||
# this takes the rquest path(doc/api) and adds users.md so the path looks like doc/api/users.md
|
||||
def build_nested_path(path, request_path)
|
||||
return path unless request_path
|
||||
if local_path(request_path) == "tree"
|
||||
base = request_path.split("/").push(path)
|
||||
base.join("/")
|
||||
else
|
||||
base = request_path.split("/")
|
||||
base.pop
|
||||
base.push(path).join("/")
|
||||
end
|
||||
end
|
||||
|
||||
def file_exists?(path)
|
||||
return false if path.nil? || path.empty?
|
||||
File.exists?(Rails.root.join(path))
|
||||
end
|
||||
|
||||
# Check if the path is pointing to a directory(tree) or a file(blob)
|
||||
# eg. doc/api is directory and doc/README.md is file
|
||||
def local_path(path)
|
||||
File.directory?(Rails.root.join(path)) ? "tree" : "blob"
|
||||
end
|
||||
|
||||
# We will assume that if no ref exists we can point to master
|
||||
def correct_ref(ref)
|
||||
ref ? ref : "master"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ module IssuesHelper
|
||||
def url_for_project_issues
|
||||
return "" if @project.nil?
|
||||
|
||||
if @project.used_default_issues_tracker?
|
||||
if @project.used_default_issues_tracker? || !external_issues_tracker_enabled?
|
||||
project_issues_path(@project)
|
||||
else
|
||||
url = Gitlab.config.issues_tracker[@project.issues_tracker]["project_url"]
|
||||
@@ -28,7 +28,7 @@ module IssuesHelper
|
||||
def url_for_new_issue
|
||||
return "" if @project.nil?
|
||||
|
||||
if @project.used_default_issues_tracker?
|
||||
if @project.used_default_issues_tracker? || !external_issues_tracker_enabled?
|
||||
url = new_project_issue_path project_id: @project
|
||||
else
|
||||
url = Gitlab.config.issues_tracker[@project.issues_tracker]["new_issue_url"]
|
||||
@@ -40,7 +40,7 @@ module IssuesHelper
|
||||
def url_for_issue(issue_iid)
|
||||
return "" if @project.nil?
|
||||
|
||||
if @project.used_default_issues_tracker?
|
||||
if @project.used_default_issues_tracker? || !external_issues_tracker_enabled?
|
||||
url = project_issue_url project_id: @project, id: issue_iid
|
||||
else
|
||||
url = Gitlab.config.issues_tracker[@project.issues_tracker]["issues_url"]
|
||||
@@ -59,4 +59,13 @@ module IssuesHelper
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
# Checks if issues_tracker setting exists in gitlab.yml
|
||||
def external_issues_tracker_enabled?
|
||||
if Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any?
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,6 @@ module ProfileHelper
|
||||
end
|
||||
|
||||
def show_profile_remove_tab?
|
||||
Gitlab.config.gitlab.signup_enabled && !current_user.ldap_user?
|
||||
gitlab_config.signup_enabled && !current_user.ldap_user?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,10 +5,10 @@ module ProjectsHelper
|
||||
|
||||
def link_to_project project
|
||||
link_to project do
|
||||
title = content_tag(:strong, project.name)
|
||||
title = content_tag(:span, project.name, class: 'projet-name')
|
||||
|
||||
if project.namespace
|
||||
namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'tiny')
|
||||
namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'namespace-name')
|
||||
title = namespace + title
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ module ProjectsHelper
|
||||
author_html = ""
|
||||
|
||||
# Build avatar image tag
|
||||
author_html << image_tag(gravatar_icon(author.try(:email), 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.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
|
||||
|
||||
# Build name span tag
|
||||
author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name]
|
||||
@@ -77,7 +77,19 @@ module ProjectsHelper
|
||||
end
|
||||
|
||||
def project_active_milestones
|
||||
@project.milestones.active.order("id desc").all
|
||||
@project.milestones.active.order("due_date, title ASC").all
|
||||
end
|
||||
|
||||
def project_issues_trackers
|
||||
values = Project.issues_tracker.values.map do |tracker_key|
|
||||
if tracker_key.to_sym == :gitlab
|
||||
['GitLab', tracker_key]
|
||||
else
|
||||
[Gitlab.config.issues_tracker[tracker_key]['title'] || tracker_key, tracker_key]
|
||||
end
|
||||
end
|
||||
|
||||
options_for_select(values)
|
||||
end
|
||||
|
||||
private
|
||||
@@ -103,4 +115,29 @@ module ProjectsHelper
|
||||
|
||||
nav_tabs.flatten
|
||||
end
|
||||
|
||||
def git_user_name
|
||||
if current_user
|
||||
current_user.name
|
||||
else
|
||||
"Your name"
|
||||
end
|
||||
end
|
||||
|
||||
def git_user_email
|
||||
if current_user
|
||||
current_user.email
|
||||
else
|
||||
"your@email.com"
|
||||
end
|
||||
end
|
||||
|
||||
def repository_size
|
||||
"#{@project.repository.size} MB"
|
||||
rescue
|
||||
# In order to prevent 500 error
|
||||
# when application cannot allocate memory
|
||||
# to calculate repo size - just show 'Unknown'
|
||||
'unknown'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
module SearchHelper
|
||||
def search_autocomplete_source
|
||||
return unless current_user
|
||||
|
||||
[
|
||||
groups_autocomplete,
|
||||
projects_autocomplete,
|
||||
default_autocomplete,
|
||||
project_autocomplete,
|
||||
help_autocomplete
|
||||
].flatten.to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Autocomplete results for various settings pages
|
||||
def default_autocomplete
|
||||
[
|
||||
{ label: "My Profile settings", url: profile_path },
|
||||
{ label: "My SSH Keys", url: profile_keys_path },
|
||||
{ label: "My Dashboard", url: root_path },
|
||||
{ label: "Admin Section", url: admin_root_path },
|
||||
]
|
||||
end
|
||||
|
||||
# Autocomplete results for internal help pages
|
||||
def help_autocomplete
|
||||
[
|
||||
{ label: "help: API Help", url: help_api_path },
|
||||
{ label: "help: Markdown Help", url: help_markdown_path },
|
||||
{ label: "help: Permissions Help", url: help_permissions_path },
|
||||
{ label: "help: Public Access Help", url: help_public_access_path },
|
||||
{ label: "help: Rake Tasks Help", url: help_raketasks_path },
|
||||
{ label: "help: SSH Keys Help", url: help_ssh_path },
|
||||
{ label: "help: System Hooks Help", url: help_system_hooks_path },
|
||||
{ label: "help: Web Hooks Help", url: help_web_hooks_path },
|
||||
{ label: "help: Workflow Help", url: help_workflow_path },
|
||||
]
|
||||
end
|
||||
|
||||
# Autocomplete results for the current project, if it's defined
|
||||
def project_autocomplete
|
||||
if @project && @project.repository.exists? && @project.repository.root_ref
|
||||
prefix = simple_sanitize(@project.name_with_namespace)
|
||||
ref = @ref || @project.repository.root_ref
|
||||
|
||||
[
|
||||
{ label: "#{prefix} - Files", url: project_tree_path(@project, ref) },
|
||||
{ label: "#{prefix} - Commits", url: project_commits_path(@project, ref) },
|
||||
{ label: "#{prefix} - Network", url: project_network_path(@project, ref) },
|
||||
{ label: "#{prefix} - Graph", url: project_graph_path(@project, ref) },
|
||||
{ label: "#{prefix} - Issues", url: project_issues_path(@project) },
|
||||
{ label: "#{prefix} - Merge Requests", url: project_merge_requests_path(@project) },
|
||||
{ label: "#{prefix} - Milestones", url: project_milestones_path(@project) },
|
||||
{ label: "#{prefix} - Snippets", url: project_snippets_path(@project) },
|
||||
{ label: "#{prefix} - Team", url: project_team_index_path(@project) },
|
||||
{ label: "#{prefix} - Wall", url: project_wall_path(@project) },
|
||||
{ label: "#{prefix} - Wiki", url: project_wikis_path(@project) },
|
||||
]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
# Autocomplete results for the current user's groups
|
||||
def groups_autocomplete
|
||||
current_user.authorized_groups.map do |group|
|
||||
{ label: "group: #{simple_sanitize(group.name)}", url: group_path(group) }
|
||||
end
|
||||
end
|
||||
|
||||
# Autocomplete results for the current user's projects
|
||||
def projects_autocomplete
|
||||
current_user.authorized_projects.map do |p|
|
||||
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -67,9 +67,9 @@ module TreeHelper
|
||||
end
|
||||
|
||||
def tree_breadcrumbs(tree, max_links = 2)
|
||||
if tree.path
|
||||
if @path.present?
|
||||
part_path = ""
|
||||
parts = tree.path.split("\/")
|
||||
parts = @path.split("\/")
|
||||
|
||||
yield('..', nil) if parts.count > max_links
|
||||
|
||||
@@ -78,14 +78,14 @@ module TreeHelper
|
||||
part_path = part if part_path.empty?
|
||||
|
||||
next unless parts.last(2).include?(part) if parts.count > max_links
|
||||
yield(part, tree_join(tree.ref, part_path))
|
||||
yield(part, tree_join(@ref, part_path))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def up_dir_path tree
|
||||
file = File.join(tree.path, "..")
|
||||
tree_join(tree.ref, file)
|
||||
file = File.join(@path, "..")
|
||||
tree_join(@ref, file)
|
||||
end
|
||||
|
||||
def leave_edit_message
|
||||
|
||||
@@ -18,7 +18,7 @@ module Emails
|
||||
@note = Note.find(note_id)
|
||||
@merge_request = @note.noteable
|
||||
@project = @note.project
|
||||
mail(to: recipient(recipient_id), subject: subject("note for merge request !#{@merge_request.iid}"))
|
||||
mail(to: recipient(recipient_id), subject: subject("note for merge request ##{@merge_request.iid}"))
|
||||
end
|
||||
|
||||
def note_wall_email(recipient_id, note_id)
|
||||
|
||||
+33
-14
@@ -1,6 +1,7 @@
|
||||
class Ability
|
||||
class << self
|
||||
def allowed(user, subject)
|
||||
return not_auth_abilities(user, subject) if user.nil?
|
||||
return [] unless user.kind_of?(User)
|
||||
return [] if user.blocked?
|
||||
|
||||
@@ -17,6 +18,34 @@ class Ability
|
||||
end.concat(global_abilities(user))
|
||||
end
|
||||
|
||||
# List of possible abilities
|
||||
# for non-authenticated user
|
||||
def not_auth_abilities(user, subject)
|
||||
project = if subject.kind_of?(Project)
|
||||
subject
|
||||
elsif subject.respond_to?(:project)
|
||||
subject.project
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
if project && project.public
|
||||
[
|
||||
:read_project,
|
||||
:read_wiki,
|
||||
:read_issue,
|
||||
:read_milestone,
|
||||
:read_project_snippet,
|
||||
:read_team_member,
|
||||
:read_merge_request,
|
||||
:read_note,
|
||||
:download_code
|
||||
]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def global_abilities(user)
|
||||
rules = []
|
||||
rules << :create_group if user.can_create_group
|
||||
@@ -50,7 +79,7 @@ class Ability
|
||||
rules << project_admin_rules
|
||||
end
|
||||
|
||||
if project.group && project.group.owners.include?(user)
|
||||
if project.group && project.group.has_owner?(user)
|
||||
rules << project_admin_rules
|
||||
end
|
||||
|
||||
@@ -58,19 +87,9 @@ class Ability
|
||||
end
|
||||
|
||||
def public_project_rules
|
||||
[
|
||||
project_guest_rules + [
|
||||
:download_code,
|
||||
:fork_project,
|
||||
:read_project,
|
||||
:read_wiki,
|
||||
:read_issue,
|
||||
:read_milestone,
|
||||
:read_project_snippet,
|
||||
:read_team_member,
|
||||
:read_merge_request,
|
||||
:read_note,
|
||||
:write_issue,
|
||||
:write_note
|
||||
]
|
||||
end
|
||||
|
||||
@@ -135,12 +154,12 @@ class Ability
|
||||
def group_abilities user, group
|
||||
rules = []
|
||||
|
||||
if group.users.include?(user)
|
||||
if group.users.include?(user) || user.admin?
|
||||
rules << :read_group
|
||||
end
|
||||
|
||||
# Only group owner and administrators can manage group
|
||||
if group.owners.include?(user) || user.admin?
|
||||
if group.has_owner?(user) || user.admin?
|
||||
rules << [
|
||||
:manage_group,
|
||||
:manage_namespace
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# title :string(255)
|
||||
# token :string(255)
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# active :boolean default(FALSE), not null
|
||||
# project_url :string(255)
|
||||
#
|
||||
|
||||
require "flowdock-git-hook"
|
||||
|
||||
class FlowdockService < Service
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'Flowdock'
|
||||
end
|
||||
|
||||
def description
|
||||
'Flowdock is a collaboration web app for technical teams.'
|
||||
end
|
||||
|
||||
def to_param
|
||||
'flowdock'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: '' }
|
||||
]
|
||||
end
|
||||
|
||||
def execute(push_data)
|
||||
repo_path = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
|
||||
Flowdock::Git.post(
|
||||
push_data[:ref],
|
||||
push_data[:before],
|
||||
push_data[:after],
|
||||
token: token,
|
||||
repo: repo_path,
|
||||
repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
|
||||
commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -45,6 +45,10 @@ class GollumWiki
|
||||
end
|
||||
end
|
||||
|
||||
def empty?
|
||||
pages.empty?
|
||||
end
|
||||
|
||||
# Returns an Array of Gitlab WikiPage instances or an
|
||||
# empty Array if this Wiki has no pages.
|
||||
def pages
|
||||
|
||||
+19
-17
@@ -5,7 +5,7 @@
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) not null
|
||||
# path :string(255) not null
|
||||
# owner_id :integer not null
|
||||
# owner_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255)
|
||||
@@ -26,36 +26,38 @@ class Group < Namespace
|
||||
presence: true,
|
||||
if: ->(group) { group.ldap_cn.present? }
|
||||
|
||||
after_create :add_owner
|
||||
|
||||
def human_name
|
||||
name
|
||||
end
|
||||
|
||||
def owners
|
||||
@owners ||= (users_groups.owners.map(&:user) << owner).uniq
|
||||
@owners ||= users_groups.owners.map(&:user)
|
||||
end
|
||||
|
||||
def add_users(user_ids, group_access)
|
||||
user_ids.compact.each do |user_id|
|
||||
self.users_groups.create(user_id: user_id, group_access: group_access)
|
||||
user = self.users_groups.find_or_initialize_by_user_id(user_id)
|
||||
user.update_attributes(group_access: group_access)
|
||||
end
|
||||
end
|
||||
|
||||
def change_owner(user)
|
||||
self.owner = user
|
||||
membership = users_groups.where(user_id: user.id).first
|
||||
|
||||
if membership
|
||||
membership.update_attributes(group_access: UsersGroup::OWNER)
|
||||
else
|
||||
add_owner
|
||||
end
|
||||
def add_user(user, group_access)
|
||||
self.users_groups.create(user_id: user.id, group_access: group_access)
|
||||
end
|
||||
|
||||
private
|
||||
def add_owner(user)
|
||||
self.add_user(user, UsersGroup::OWNER)
|
||||
end
|
||||
|
||||
def add_owner
|
||||
self.add_users([owner.id], UsersGroup::OWNER)
|
||||
def has_owner?(user)
|
||||
owners.include?(user)
|
||||
end
|
||||
|
||||
def last_owner?(user)
|
||||
has_owner?(user) && owners.size == 1
|
||||
end
|
||||
|
||||
def members
|
||||
users_groups
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# merge_status :string(255)
|
||||
# target_project_id :integer not null
|
||||
# iid :integer
|
||||
# description :text
|
||||
#
|
||||
|
||||
require Rails.root.join("app/models/commit")
|
||||
@@ -221,7 +222,11 @@ class MergeRequest < ActiveRecord::Base
|
||||
|
||||
def mr_and_commit_notes
|
||||
commit_ids = commits.map(&:id)
|
||||
Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
|
||||
project.notes.where(
|
||||
"(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
|
||||
mr_id: id,
|
||||
commit_ids: commit_ids
|
||||
)
|
||||
end
|
||||
|
||||
# Returns the raw diff for this merge request
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# id :integer not null, primary key
|
||||
# name :string(255) not null
|
||||
# path :string(255) not null
|
||||
# owner_id :integer not null
|
||||
# owner_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# type :string(255)
|
||||
@@ -20,7 +20,7 @@ class Namespace < ActiveRecord::Base
|
||||
has_many :projects, dependent: :destroy
|
||||
belongs_to :owner, class_name: "User"
|
||||
|
||||
validates :owner, presence: true
|
||||
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
|
||||
validates :name, presence: true, uniqueness: true,
|
||||
length: { within: 0..255 },
|
||||
format: { with: Gitlab::Regex.name_regex,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
require "grit"
|
||||
|
||||
module Network
|
||||
class Commit
|
||||
include ActionView::Helpers::TagHelper
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# commit_id :string(255)
|
||||
# noteable_id :integer
|
||||
# st_diff :text
|
||||
# system :boolean default(FALSE), not null
|
||||
#
|
||||
|
||||
require 'carrierwave/orm/activerecord'
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# active :boolean default(FALSE), not null
|
||||
# project_url :string(255)
|
||||
# subdomain :string(255)
|
||||
# room :string(255)
|
||||
#
|
||||
|
||||
class PivotaltrackerService < Service
|
||||
|
||||
+10
-11
@@ -24,8 +24,6 @@
|
||||
# import_url :string(255)
|
||||
#
|
||||
|
||||
require "grit"
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
include Gitlab::ShellAdapter
|
||||
extend Enumerize
|
||||
@@ -48,12 +46,14 @@ class Project < ActiveRecord::Base
|
||||
has_one :campfire_service, dependent: :destroy
|
||||
has_one :pivotaltracker_service, dependent: :destroy
|
||||
has_one :hipchat_service, dependent: :destroy
|
||||
has_one :flowdock_service, dependent: :destroy
|
||||
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
|
||||
has_one :forked_from_project, through: :forked_project_link
|
||||
|
||||
has_many :services, dependent: :destroy
|
||||
has_many :events, dependent: :destroy
|
||||
has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id"
|
||||
has_many :fork_merge_requests,dependent: :destroy, foreign_key: "source_project_id", class_name: MergeRequest
|
||||
has_many :issues, dependent: :destroy, order: "state DESC, created_at DESC"
|
||||
has_many :milestones, dependent: :destroy
|
||||
has_many :notes, dependent: :destroy
|
||||
@@ -224,7 +224,7 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def available_services_names
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker)
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker flowdock)
|
||||
end
|
||||
|
||||
def gitlab_ci?
|
||||
@@ -252,10 +252,10 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def owner
|
||||
if namespace
|
||||
namespace_owner
|
||||
if group
|
||||
group
|
||||
else
|
||||
creator
|
||||
namespace.try(:owner)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -279,10 +279,6 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def namespace_owner
|
||||
namespace.try(:owner)
|
||||
end
|
||||
|
||||
def path_with_namespace
|
||||
if namespace
|
||||
namespace.path + '/' + path
|
||||
@@ -320,8 +316,11 @@ class Project < ActiveRecord::Base
|
||||
branch_name = ref.gsub("refs/heads/", "")
|
||||
c_ids = self.repository.commits_between(oldrev, newrev).map(&:id)
|
||||
|
||||
# Update code for merge requests
|
||||
# Update code for merge requests into project between project branches
|
||||
mrs = self.merge_requests.opened.by_branch(branch_name).all
|
||||
# Update code for merge requests between project and project fork
|
||||
mrs += self.fork_merge_requests.opened.by_branch(branch_name).all
|
||||
|
||||
mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
|
||||
|
||||
# Close merge requests
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
class Repository
|
||||
include Gitlab::ShellAdapter
|
||||
|
||||
attr_accessor :raw_repository
|
||||
attr_accessor :raw_repository, :path_with_namespace
|
||||
|
||||
def initialize(path_with_namespace, default_branch)
|
||||
@raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch)
|
||||
@path_with_namespace = path_with_namespace
|
||||
@raw_repository = Gitlab::Git::Repository.new(path_to_repo) if path_with_namespace
|
||||
rescue Gitlab::Git::Repository::NoRepository
|
||||
nil
|
||||
end
|
||||
|
||||
def path_to_repo
|
||||
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, path_with_namespace + ".git")
|
||||
end
|
||||
|
||||
def exists?
|
||||
raw_repository
|
||||
end
|
||||
@@ -150,4 +155,8 @@ class Repository
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def blob_at(sha, path)
|
||||
Gitlab::Git::Blob.find(self, sha, path)
|
||||
end
|
||||
end
|
||||
|
||||
+17
-8
@@ -1,17 +1,26 @@
|
||||
class Tree
|
||||
attr_accessor :raw
|
||||
attr_accessor :entries, :readme
|
||||
|
||||
def initialize(repository, sha, ref = nil, path = nil)
|
||||
@raw = Gitlab::Git::Tree.new(repository, sha, ref, path)
|
||||
def initialize(repository, sha, path = '/')
|
||||
path = '/' if path.blank?
|
||||
git_repo = repository.raw_repository
|
||||
@entries = Gitlab::Git::Tree.where(git_repo, sha, path)
|
||||
|
||||
if readme_tree = @entries.find(&:readme?)
|
||||
readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
|
||||
@readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
|
||||
end
|
||||
end
|
||||
|
||||
def method_missing(m, *args, &block)
|
||||
@raw.send(m, *args, &block)
|
||||
def trees
|
||||
@entries.select(&:dir?)
|
||||
end
|
||||
|
||||
def respond_to?(method)
|
||||
return true if @raw.respond_to?(method)
|
||||
def blobs
|
||||
@entries.select(&:file?)
|
||||
end
|
||||
|
||||
super
|
||||
def submodules
|
||||
@entries.select(&:submodule?)
|
||||
end
|
||||
end
|
||||
|
||||
+14
-11
@@ -38,13 +38,16 @@
|
||||
# created_by_id :integer
|
||||
#
|
||||
|
||||
require 'carrierwave/orm/activerecord'
|
||||
require 'file_size_validator'
|
||||
|
||||
class User < ActiveRecord::Base
|
||||
devise :database_authenticatable, :token_authenticatable, :lockable,
|
||||
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :registerable
|
||||
devise :database_authenticatable, :token_authenticatable, :lockable, :async,
|
||||
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable
|
||||
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
|
||||
:skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password,
|
||||
:extern_uid, :provider, :password_expires_at,
|
||||
:extern_uid, :provider, :password_expires_at, :avatar,
|
||||
as: [:default, :admin]
|
||||
|
||||
attr_accessible :projects_limit, :can_create_group,
|
||||
@@ -113,6 +116,8 @@ class User < ActiveRecord::Base
|
||||
|
||||
validate :namespace_uniq, if: ->(user) { user.username_changed? }
|
||||
|
||||
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
|
||||
|
||||
before_validation :generate_password, on: :create
|
||||
before_validation :sanitize_attrs
|
||||
|
||||
@@ -135,7 +140,7 @@ class User < ActiveRecord::Base
|
||||
# Remove user from all groups
|
||||
user.users_groups.find_each do |membership|
|
||||
# skip owned resources
|
||||
next if membership.group.owners.include?(user)
|
||||
next if membership.group.last_owner?(user)
|
||||
|
||||
return false unless membership.destroy
|
||||
end
|
||||
@@ -150,6 +155,8 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
mount_uploader :avatar, AttachmentUploader
|
||||
|
||||
# Scopes
|
||||
scope :admins, -> { where(admin: true) }
|
||||
scope :blocked, -> { with_state(:blocked) }
|
||||
@@ -167,7 +174,7 @@ class User < ActiveRecord::Base
|
||||
# Class methods
|
||||
#
|
||||
class << self
|
||||
# Devise method overridden to allow sing in with email or username
|
||||
# Devise method overridden to allow sign in with email or username
|
||||
def find_for_database_authentication(warden_conditions)
|
||||
conditions = warden_conditions.dup
|
||||
if login = conditions.delete(:login)
|
||||
@@ -192,11 +199,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def by_username_or_id(name_or_id)
|
||||
if (name_or_id.is_a?(Integer))
|
||||
User.find_by_id(name_or_id)
|
||||
else
|
||||
User.find_by_username(name_or_id)
|
||||
end
|
||||
where('username = ? OR id = ?', name_or_id, name_or_id).first
|
||||
end
|
||||
|
||||
def build_user(attrs = {}, options= {})
|
||||
@@ -211,7 +214,7 @@ class User < ActiveRecord::Base
|
||||
{
|
||||
projects_limit: Gitlab.config.gitlab.default_projects_limit,
|
||||
can_create_group: Gitlab.config.gitlab.default_can_create_group,
|
||||
theme_id: Gitlab::Theme::MARS
|
||||
theme_id: Gitlab.config.gitlab.default_theme
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,17 @@ class ProjectObserver < BaseObserver
|
||||
|
||||
log_info("#{project.owner.name} created a new project \"#{project.name_with_namespace}\"")
|
||||
end
|
||||
|
||||
if project.wiki_enabled?
|
||||
begin
|
||||
# force the creation of a wiki,
|
||||
GollumWiki.new(project, project.owner).wiki
|
||||
rescue GollumWiki::CouldNotCreateWikiError => ex
|
||||
# Prevent project observer crash
|
||||
# if failed to create wiki
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def after_update(project)
|
||||
|
||||
@@ -112,6 +112,7 @@ class GitPushService
|
||||
# ref: String,
|
||||
# user_id: String,
|
||||
# user_name: String,
|
||||
# project_id: String,
|
||||
# repository: {
|
||||
# name: String,
|
||||
# url: String,
|
||||
@@ -136,6 +137,7 @@ class GitPushService
|
||||
ref: ref,
|
||||
user_id: user.id,
|
||||
user_name: user.name,
|
||||
project_id: project.id,
|
||||
repository: {
|
||||
name: project.name,
|
||||
url: project.url_to_repo,
|
||||
|
||||
@@ -23,18 +23,21 @@ class SystemHooksService
|
||||
|
||||
case model
|
||||
when Project
|
||||
owner = model.owner
|
||||
|
||||
data.merge!({
|
||||
name: model.name,
|
||||
path: model.path,
|
||||
path_with_namespace: model.path_with_namespace,
|
||||
project_id: model.id,
|
||||
owner_name: model.owner.name,
|
||||
owner_email: model.owner.email
|
||||
owner_name: owner.name,
|
||||
owner_email: owner.respond_to?(:email) ? owner.email : nil
|
||||
})
|
||||
when User
|
||||
data.merge!({
|
||||
name: model.name,
|
||||
email: model.email
|
||||
email: model.email,
|
||||
user_id: model.id
|
||||
})
|
||||
when UsersProject
|
||||
data.merge!({
|
||||
|
||||
@@ -2,3 +2,37 @@
|
||||
%br
|
||||
.ui-box
|
||||
%iframe{src: sidekiq_path, width: '100%', height: 900, style: "border: none"}
|
||||
%h4 Sidekiq running processes
|
||||
- sidekiq_processes = `ps -eo euser,pid,pcpu,pmem,stat,start,command | grep sidekiq | grep -v grep`
|
||||
- if sidekiq_processes.empty?
|
||||
%b There are no running sidekiq processes
|
||||
%b Please restart GitLab
|
||||
- else
|
||||
.ui-box
|
||||
%table.zebra-striped
|
||||
%thead
|
||||
%th USER
|
||||
%th
|
||||
%th PID
|
||||
%th
|
||||
%th CPU
|
||||
%th
|
||||
%th MEM
|
||||
%th
|
||||
%th STATE
|
||||
%th
|
||||
%th START
|
||||
%th
|
||||
%th COMMAND
|
||||
%th
|
||||
- sidekiq_processes.split("\n").each do |process|
|
||||
- next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/)
|
||||
- data = process.gsub!(/\s+/m, '|').strip.split('|')
|
||||
%tr
|
||||
- 6.times do
|
||||
%td= data.shift
|
||||
%td
|
||||
%td= data.join(" ")
|
||||
%b If '[25 of 25 busy]' is shown, restart GitLab with 'sudo service gitlab reload'.
|
||||
%br
|
||||
%b If more than one sidekiq process is listed, stop GitLab, kill the remaining sidekiq processes (sudo pkill -u git -f sidekiq) and restart GitLab.
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
%h3.page-title
|
||||
Admin area
|
||||
%p.light
|
||||
You can manage projects, users and other GitLab data from here.
|
||||
%hr
|
||||
.admin_dash.row
|
||||
.span4
|
||||
.ui-box
|
||||
.title Projects
|
||||
.data.padded
|
||||
.light-well
|
||||
%h4 Projects
|
||||
.data
|
||||
= link_to admin_projects_path do
|
||||
%h1= Project.count
|
||||
%hr
|
||||
= link_to 'New Project', new_project_path, class: "btn btn-small"
|
||||
= link_to 'New Project', new_project_path, class: "btn btn-new"
|
||||
.span4
|
||||
.ui-box
|
||||
.title Users
|
||||
.data.padded
|
||||
.light-well
|
||||
%h4 Users
|
||||
.data
|
||||
= link_to admin_users_path do
|
||||
%h1= User.count
|
||||
%hr
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-small"
|
||||
= link_to 'New User', new_admin_user_path, class: "btn btn-new"
|
||||
.span4
|
||||
.ui-box
|
||||
.title Groups
|
||||
.data.padded
|
||||
.light-well
|
||||
%h4 Groups
|
||||
.data
|
||||
= link_to admin_groups_path do
|
||||
%h1= Group.count
|
||||
%hr
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-small"
|
||||
= link_to 'New Group', new_admin_group_path, class: "btn btn-new"
|
||||
|
||||
.row
|
||||
.row.prepend-top-10
|
||||
.span4
|
||||
%h4 Latest projects
|
||||
%hr
|
||||
|
||||
@@ -31,11 +31,8 @@
|
||||
|
||||
.clearfix.light.append-bottom-10
|
||||
%span
|
||||
%b Owner:
|
||||
- if group.owner
|
||||
= link_to group.owner_name, admin_user_path(group.owner)
|
||||
- else
|
||||
(deleted)
|
||||
%b Members:
|
||||
%span.badge= group.members.size
|
||||
\|
|
||||
%span
|
||||
%b Projects:
|
||||
|
||||
@@ -24,26 +24,6 @@
|
||||
%strong
|
||||
= @group.description
|
||||
|
||||
%li
|
||||
%span.light Owned by:
|
||||
%strong
|
||||
- if @group.owner
|
||||
= link_to @group.owner_name, admin_user_path(@group.owner)
|
||||
- else
|
||||
(deleted)
|
||||
.pull-right
|
||||
= link_to "#", class: "btn btn-small change-owner-link" do
|
||||
%i.icon-edit
|
||||
Change owner
|
||||
%li.change-owner-holder.hide.bgred
|
||||
.form-holder
|
||||
%strong.cred New Owner:
|
||||
= form_for [:admin, @group] do |f|
|
||||
= users_select_tag(:"group[owner_id]")
|
||||
.prepend-top-10
|
||||
= f.submit 'Change Owner', class: "btn btn-remove"
|
||||
= link_to "Cancel", "#", class: "btn change-owner-cancel-link"
|
||||
|
||||
%li
|
||||
%span.light Created at:
|
||||
%strong
|
||||
@@ -92,4 +72,5 @@
|
||||
= link_to user.name, admin_user_path(user)
|
||||
%span.pull-right.light
|
||||
= member.human_access
|
||||
|
||||
= link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
|
||||
%i.icon-minus.icon-white
|
||||
|
||||
@@ -52,7 +52,8 @@
|
||||
"created_at": "2012-07-21T07:44:07Z",
|
||||
"email": "js@gitlabhq.com",
|
||||
"event_name": "user_create",
|
||||
"name": "John Smith"
|
||||
"name": "John Smith",
|
||||
"user_id": 41
|
||||
}
|
||||
|
||||
6. User removed:
|
||||
@@ -60,7 +61,8 @@
|
||||
"created_at": "2012-07-21T07:44:07Z",
|
||||
"email": "js@gitlabhq.com",
|
||||
"event_name": "user_destroy",
|
||||
"name": "John Smith"
|
||||
"name": "John Smith",
|
||||
"user_id": 41
|
||||
}
|
||||
|
||||
eos
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
.alert.alert-info
|
||||
%span
|
||||
Post-receive hooks for binding events.
|
||||
%br
|
||||
Read more about system hooks
|
||||
%strong #{link_to "here", help_system_hooks_path, class: "vlink"}
|
||||
%h3.page-title
|
||||
System Hooks
|
||||
|
||||
%p.light
|
||||
#{link_to "System hooks ", help_system_hooks_path, class: "vlink"} can be
|
||||
used for binding events when GitLab creates a User or Project.
|
||||
|
||||
%hr
|
||||
|
||||
|
||||
= form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
|
||||
-if @hook.errors.any?
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
%span.light Owned by:
|
||||
%strong
|
||||
- if @project.owner
|
||||
= link_to @project.owner_name, admin_user_path(@project.owner)
|
||||
= link_to @project.owner_name, [:admin, @project.owner]
|
||||
- else
|
||||
(deleted)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%h3.page-title
|
||||
User:
|
||||
%span.cgray User:
|
||||
= @user.name
|
||||
- if @user.blocked?
|
||||
%span.cred (Blocked)
|
||||
@@ -10,8 +10,6 @@
|
||||
= link_to edit_admin_user_path(@user), class: "btn grouped" do
|
||||
%i.icon-edit
|
||||
Edit
|
||||
- if @user.blocked?
|
||||
= link_to 'Unblock', unblock_admin_user_path(@user), method: :put, class: "btn grouped success"
|
||||
%hr
|
||||
|
||||
.row
|
||||
@@ -20,7 +18,7 @@
|
||||
.title
|
||||
Account:
|
||||
.pull-right
|
||||
= image_tag gravatar_icon(@user.email, 32), class: "avatar s32"
|
||||
= image_tag avatar_icon(@user.email, 32), class: "avatar s32"
|
||||
%ul.well-list
|
||||
%li
|
||||
%span.light Name:
|
||||
@@ -67,17 +65,30 @@
|
||||
= link_to @user.created_by.name, [:admin, @user.created_by]
|
||||
|
||||
- unless @user == current_user
|
||||
.alert
|
||||
%h4 Block user
|
||||
%br
|
||||
%p Blocking user has the following effects:
|
||||
%ul
|
||||
%li User will not be able to login
|
||||
%li User will not be able to access git repositories
|
||||
%li User will be removed from joined projects and groups
|
||||
%li Personal projects will be left
|
||||
%li Owned groups will be left
|
||||
= link_to 'Block user', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-remove"
|
||||
- if @user.blocked?
|
||||
.alert.alert-info
|
||||
%h4 This user is blocked
|
||||
%br
|
||||
%p Blocking user has the following effects:
|
||||
%ul
|
||||
%li User will not be able to login
|
||||
%li User will not be able to access git repositories
|
||||
%li User will be removed from joined projects and groups
|
||||
%li Personal projects will be left
|
||||
%li Owned groups will be left
|
||||
= link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-new", confirm: 'Are you sure?'
|
||||
- else
|
||||
.alert
|
||||
%h4 Block this user
|
||||
%br
|
||||
%p Blocking user has the following effects:
|
||||
%ul
|
||||
%li User will not be able to login
|
||||
%li User will not be able to access git repositories
|
||||
%li User will be removed from joined projects and groups
|
||||
%li Personal projects will be left
|
||||
%li Owned groups will be left
|
||||
= link_to 'Block user', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-remove"
|
||||
|
||||
.alert.alert-error
|
||||
%h4
|
||||
@@ -117,11 +128,7 @@
|
||||
- tm = project.team.find_tm(@user.id)
|
||||
%li.users_project
|
||||
= link_to admin_project_path(project), class: dom_class(project) do
|
||||
- if project.namespace
|
||||
= project.namespace.human_name
|
||||
\/
|
||||
%strong.well-title
|
||||
= truncate(project.name, length: 45)
|
||||
= project.name_with_namespace
|
||||
|
||||
- if tm
|
||||
.pull-right
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
= truncate(group.name, length: 35)
|
||||
%span.arrow
|
||||
%i.icon-angle-right
|
||||
%span.owner-info
|
||||
%span Owner:
|
||||
%span.owner= group.owner_name
|
||||
- if groups.blank?
|
||||
%li
|
||||
%h3.nothing_here_message You have no groups yet.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
= link_to project_path(project), class: dom_class(project) do
|
||||
%span.namespace-name
|
||||
- if project.namespace
|
||||
= project.namespace.human_name
|
||||
\/
|
||||
%span.project-name.filter-title
|
||||
= truncate(project.name, length: 25)
|
||||
%span.arrow
|
||||
%i.icon-angle-right
|
||||
%span.last-activity
|
||||
%span Last activity:
|
||||
%span.date= project_last_activity(project)
|
||||
@@ -10,21 +10,16 @@
|
||||
%ul.well-list.dash-list
|
||||
- projects.each do |project|
|
||||
%li.project-row
|
||||
= link_to project_path(project), class: dom_class(project) do
|
||||
%span.namespace-name
|
||||
- if project.namespace
|
||||
= project.namespace.human_name
|
||||
\/
|
||||
%span.project-name.filter-title
|
||||
= truncate(project.name, length: 25)
|
||||
%span.arrow
|
||||
%i.icon-angle-right
|
||||
%span.last-activity
|
||||
%span Last activity:
|
||||
%span.date= project_last_activity(project)
|
||||
= render "project", project: project
|
||||
|
||||
- if projects.blank?
|
||||
%li
|
||||
%h3.nothing_here_message There are no projects here.
|
||||
- if @projects_count > 20
|
||||
- if @projects_count > @projects_limit
|
||||
%li.bottom
|
||||
%strong= link_to "show all projects", projects_dashboard_path
|
||||
%span.light
|
||||
#{@projects_limit} of #{pluralize(@projects_count, 'project')} displayed.
|
||||
.pull-right.append-right-10
|
||||
= link_to projects_dashboard_path do
|
||||
Show all
|
||||
%i.icon-angle-right
|
||||
|
||||
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
|
||||
xml.link :href => project_issue_url(issue.project, issue)
|
||||
xml.title truncate(issue.title, :length => 80)
|
||||
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
|
||||
xml.author do |author|
|
||||
xml.name issue.author_name
|
||||
xml.email issue.author_email
|
||||
|
||||
@@ -17,7 +17,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
|
||||
xml.link :href => event_link
|
||||
xml.title truncate(event_title, :length => 80)
|
||||
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
|
||||
xml.author do |author|
|
||||
xml.name event.author_name
|
||||
xml.email event.author_email
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
= render 'devise/sessions/oauth_providers' if devise_mapping.omniauthable?
|
||||
|
||||
- if Gitlab.config.gitlab.signup_enabled
|
||||
- if gitlab_config.signup_enabled
|
||||
%hr
|
||||
%div
|
||||
Don't have an account?
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' && gitlab_config.signup_enabled %>
|
||||
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#{time_ago_in_words(event.created_at)} ago.
|
||||
|
||||
= cache event do
|
||||
= image_tag gravatar_icon(event.author_email), class: "avatar s24", alt:''
|
||||
= image_tag avatar_icon(event.author_email), class: "avatar s24", alt:''
|
||||
|
||||
- if event.push?
|
||||
= render "events/event/push", event: event
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
= link_to project_commits_path(event.project, event.ref_name) do
|
||||
%strong= truncate(event.ref_name, length: 30)
|
||||
at
|
||||
%strong= link_to_project event.project
|
||||
= link_to_project event.project
|
||||
|
||||
- if event.push_with_commits?
|
||||
- project = event.project
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
Projects
|
||||
%li
|
||||
= link_to 'LDAP', '#tab-ldap', 'data-toggle' => 'tab'
|
||||
%li
|
||||
= link_to 'Transfer', '#tab-transfer', 'data-toggle' => 'tab'
|
||||
%li
|
||||
= link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab'
|
||||
|
||||
@@ -87,17 +85,6 @@
|
||||
.form-actions
|
||||
= f.submit 'Save group', class: "btn btn-save"
|
||||
|
||||
.tab-pane#tab-transfer
|
||||
.ui-box.ui-box-danger
|
||||
.title Transfer group
|
||||
.ui-box-body
|
||||
%p
|
||||
Transferring group will cause loss of admin control over group and all child projects
|
||||
= form_for @group do |f|
|
||||
= users_select_tag(:'group[owner_id]')
|
||||
%hr
|
||||
= f.submit 'Transfer group', class: "btn btn-small btn-remove"
|
||||
|
||||
.tab-pane#tab-remove
|
||||
.ui-box.ui-box-danger
|
||||
.title Remove group
|
||||
|
||||
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
|
||||
xml.link :href => project_issue_url(issue.project, issue)
|
||||
xml.title truncate(issue.title, :length => 80)
|
||||
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
|
||||
xml.author do |author|
|
||||
xml.name issue.author_name
|
||||
xml.email issue.author_email
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
Group members
|
||||
%p.light
|
||||
Members of group have access to all group projects.
|
||||
Read more about permissions
|
||||
%strong= link_to "here", help_permissions_path, class: "vlink"
|
||||
|
||||
%hr
|
||||
- can_manage_group = current_user.can? :manage_group, @group
|
||||
.ui-box
|
||||
|
||||
@@ -16,7 +16,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
|
||||
xml.link :href => event_link
|
||||
xml.title truncate(event_title, :length => 80)
|
||||
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
|
||||
xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
|
||||
xml.author do |author|
|
||||
xml.name event.author_name
|
||||
xml.email event.author_email
|
||||
|
||||
@@ -30,5 +30,8 @@
|
||||
%li
|
||||
%strong= link_to "Public Access", help_public_access_path
|
||||
|
||||
%li
|
||||
%strong= link_to "Security", help_security_path
|
||||
|
||||
.span9.pull-right
|
||||
= yield
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
%p Get familiar with GitLab's permission levels.
|
||||
|
||||
%li
|
||||
%strong= link_to "API", help_api_path
|
||||
%strong= link_to "API", help_api_file_path(category: 'README')
|
||||
%p Explore how you can access GitLab via a simple and powerful API.
|
||||
|
||||
%li
|
||||
@@ -80,3 +80,7 @@
|
||||
%li
|
||||
%strong= link_to "Public Access", help_public_access_path
|
||||
%p Learn how you can allow public access to a project.
|
||||
|
||||
%li
|
||||
%strong= link_to "Security", help_security_path
|
||||
%p Learn what you can do to secure your GitLab instance.
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
= render layout: 'help/layout' do
|
||||
%h3.page-title Permissions
|
||||
%p.light Users have different abilities depending on the access level they have in particular group or project.
|
||||
%p.light If a user is both in a project group and in the project itself the highest permission level is used.
|
||||
%p.light If a user is a GitLab administrator they receive all permissions.
|
||||
%hr
|
||||
|
||||
%h4 Project:
|
||||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
@@ -158,3 +163,50 @@
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
|
||||
%h4 Group
|
||||
%table.table
|
||||
%thead
|
||||
%tr
|
||||
%th Action
|
||||
%th Guest
|
||||
%th Reporter
|
||||
%th Developer
|
||||
%th Master
|
||||
%th Owner
|
||||
%tbody
|
||||
%tr
|
||||
%td Browse group
|
||||
%td.permission-x ✓
|
||||
%td.permission-x ✓
|
||||
%td.permission-x ✓
|
||||
%td.permission-x ✓
|
||||
%td.permission-x ✓
|
||||
%tr
|
||||
%td Edit group
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
%tr
|
||||
%td Create project in group
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
%tr
|
||||
%td Manage group members
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
%tr
|
||||
%td Remove group
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td
|
||||
%td.permission-x ✓
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user