Merge branch 'upstream/6-2-stable' of /home/git/repositories/gitlab/gitlab-ee

This commit is contained in:
Dmitriy Zaporozhets
2013-10-31 15:06:12 +00:00
298 changed files with 4474 additions and 2248 deletions
+1
View File
@@ -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
View File
@@ -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"
+23
View File
@@ -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.
+10 -2
View File
@@ -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
View File
@@ -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
+9 -8
View File
@@ -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/)
+1 -1
View File
@@ -1 +1 @@
6.1.0-ee
6.2.0-ee
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

+10
View File
@@ -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>"
+5 -42
View File
@@ -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;
}
}
}
+1 -1
View File
@@ -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;
}
}
+2 -2
View File
@@ -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;
}
+3 -2
View File
@@ -1,7 +1,8 @@
/* Login Page */
body.login-page{
background: #474D57;
.container .content { padding-top: 4%; }
.container > .content {
padding-top: 20px;
}
}
.login-box{
+5 -1
View File
@@ -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;
}
+8 -16
View File
@@ -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;
}
}
+16 -25
View File
@@ -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 {
+1 -1
View File
@@ -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?
+2 -9
View File
@@ -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
+15 -1
View File
@@ -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 -1
View File
@@ -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)
+2 -10
View File
@@ -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
+1 -23
View File
@@ -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
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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 -2
View File
@@ -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)
+2 -2
View File
@@ -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
+2 -1
View File
@@ -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
+15 -7
View File
@@ -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
+2 -13
View File
@@ -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
+1 -1
View File
@@ -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.' }
+10 -44
View File
@@ -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
+1 -1
View File
@@ -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
+102 -1
View File
@@ -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
+12 -3
View File
@@ -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
+1 -1
View File
@@ -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
+41 -4
View File
@@ -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
+78
View File
@@ -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
+5 -5
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
+52
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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
+6 -1
View File
@@ -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
+2 -2
View File
@@ -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,
-2
View File
@@ -1,5 +1,3 @@
require "grit"
module Network
class Commit
include ActionView::Helpers::TagHelper
+1
View File
@@ -14,6 +14,7 @@
# commit_id :string(255)
# noteable_id :integer
# st_diff :text
# system :boolean default(FALSE), not null
#
require 'carrierwave/orm/activerecord'
+3
View File
@@ -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
View File
@@ -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
+11 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+11
View File
@@ -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)
+2
View File
@@ -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,
+6 -3
View File
@@ -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.
+18 -13
View File
@@ -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
+2 -5
View File
@@ -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:
+2 -21
View File
@@ -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
+4 -2
View File
@@ -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
+9 -6
View File
@@ -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?
+1 -1
View File
@@ -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)
+27 -20
View File
@@ -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
-3
View File
@@ -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.
+12
View File
@@ -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)
+9 -14
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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?
+1 -1
View File
@@ -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 -%>
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
-13
View File
@@ -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
+1 -1
View File
@@ -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
+3
View File
@@ -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
+1 -1
View File
@@ -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
+3
View File
@@ -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
+5 -1
View File
@@ -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.
+52
View File
@@ -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 &#10003;
%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 &#10003;
%td.permission-x &#10003;
%td.permission-x &#10003;
%td.permission-x &#10003;
%td.permission-x &#10003;
%tr
%td Edit group
%td
%td
%td
%td
%td.permission-x &#10003;
%tr
%td Create project in group
%td
%td
%td
%td
%td.permission-x &#10003;
%tr
%td Manage group members
%td
%td
%td
%td
%td.permission-x &#10003;
%tr
%td Remove group
%td
%td
%td
%td
%td.permission-x &#10003;

Some files were not shown because too many files have changed in this diff Show More