Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Denisov <1101.debian@gmail.com>2012-09-26 17:14:47 +0400
committerAlex Denisov <1101.debian@gmail.com>2012-09-26 17:14:47 +0400
commitc09d233611e00328f0e8d493a106737f0638d9a2 (patch)
tree351383104571ab0fb536506918860c7eb50a0eeb
parente6ce47291b3f08ebe18c2450fc4f21a2a3a2b8a9 (diff)
parent3c132f2e6896c7c1aa787ddc61ae230d9a205700 (diff)
Merge branch 'master' into fix_project_access_notification
-rw-r--r--CHANGELOG7
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock2
-rw-r--r--Guardfile1
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/application.js1
-rw-r--r--app/assets/stylesheets/application.css1
-rw-r--r--app/assets/stylesheets/common.scss81
-rw-r--r--app/assets/stylesheets/gitlab_bootstrap/lists.scss4
-rw-r--r--app/assets/stylesheets/main.scss1
-rw-r--r--app/assets/stylesheets/sections/commits.scss46
-rw-r--r--app/assets/stylesheets/sections/events.scss118
-rw-r--r--app/assets/stylesheets/sections/notes.scss6
-rw-r--r--app/controllers/admin/users_controller.rb6
-rw-r--r--app/controllers/commits_controller.rb1
-rw-r--r--app/controllers/hooks_controller.rb1
-rw-r--r--app/controllers/issues_controller.rb1
-rw-r--r--app/controllers/labels_controller.rb1
-rw-r--r--app/controllers/merge_requests_controller.rb1
-rw-r--r--app/controllers/milestones_controller.rb1
-rw-r--r--app/controllers/snippets_controller.rb1
-rw-r--r--app/helpers/tree_helper.rb8
-rw-r--r--app/models/commit.rb12
-rw-r--r--app/models/event.rb1
-rw-r--r--app/models/user.rb5
-rw-r--r--app/roles/repository.rb8
-rw-r--r--app/views/commits/compare.html.haml28
-rw-r--r--app/views/events/_commit.html.haml2
-rw-r--r--app/views/events/_event.html.haml17
-rw-r--r--app/views/events/_event_issue.html.haml17
-rw-r--r--app/views/events/_event_last_push.html.haml2
-rw-r--r--app/views/events/_event_membership_changed.html.haml14
-rw-r--r--app/views/events/_event_merge_request.html.haml26
-rw-r--r--app/views/events/_event_push.html.haml40
-rw-r--r--app/views/help/api.html.haml137
-rw-r--r--app/views/notes/_common_form.html.haml11
-rw-r--r--app/views/refs/_tree.html.haml6
-rw-r--r--app/views/refs/_tree_file.html.haml6
-rw-r--r--config/initializers/4_resque.rb31
-rw-r--r--config/initializers/4_resque_queues.rb1
-rw-r--r--config/initializers/resque.rb8
-rw-r--r--config/initializers/resque_authentication.rb14
-rw-r--r--config/initializers/resque_mailer.rb1
-rw-r--r--config/unicorn.rb.example2
-rw-r--r--doc/api/README.md3
-rw-r--r--doc/api/keys.md79
-rw-r--r--doc/api/projects.md195
-rw-r--r--doc/api/repositories.md166
-rw-r--r--doc/api/session.md22
-rw-r--r--doc/api/users.md78
-rw-r--r--features/steps/dashboard/dashboard.rb2
-rw-r--r--lib/api.rb2
-rw-r--r--lib/api/entities.rb25
-rw-r--r--lib/api/helpers.rb2
-rw-r--r--lib/api/keys.rb50
-rw-r--r--lib/api/milestones.rb6
-rw-r--r--lib/api/projects.rb115
-rw-r--r--lib/api/session.rb20
-rw-r--r--lib/api/users.rb59
-rw-r--r--lib/gitlab/graph_commit.rb4
-rw-r--r--lib/tasks/bulk_add_permission.rake28
-rw-r--r--lib/tasks/bulk_import.rake74
-rw-r--r--lib/tasks/gitlab/backup.rake46
-rw-r--r--lib/tasks/gitlab/enable_automerge.rake2
-rw-r--r--lib/tasks/gitlab/gitolite_rebuild.rake5
-rw-r--r--lib/tasks/gitlab/setup.rake3
-rw-r--r--lib/tasks/gitlab/status.rake37
-rw-r--r--lib/tasks/gitlab/write_hook.rake2
-rw-r--r--spec/helpers/tree_helper_spec.rb2
-rw-r--r--spec/models/user_spec.rb26
-rw-r--r--spec/requests/api/projects_spec.rb75
-rw-r--r--spec/requests/api/session_spec.rb39
-rw-r--r--spec/requests/api/ssh_keys_spec.rb73
-rw-r--r--spec/requests/api/users_spec.rb67
74 files changed, 1150 insertions, 838 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 7322efbf228..3fec2d86dfc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v 2.9.1
+ - Fixed resque custom config init
+
v 2.9.0
- fixed inline notes bugs
- refactored rspecs
@@ -9,8 +12,10 @@ v 2.9.0
- scss refactoring. gitlab_bootstrap/ dir
- fix git push http body bigger than 112k problem
- list of labels page under issues tab
- - API for milestones
+ - API for milestones, keys
- restyled buttons
+ - OAuth
+ - Comment order changed
v 2.8.1
- ability to disable gravatars
diff --git a/Gemfile b/Gemfile
index b17d9cf3bd1..71eafabaa91 100644
--- a/Gemfile
+++ b/Gemfile
@@ -96,6 +96,7 @@ group :assets do
gem "therubyracer"
gem 'chosen-rails'
+ gem 'jquery-atwho-rails', '0.1.6'
gem "jquery-rails", "2.0.2"
gem "jquery-ui-rails", "0.5.0"
gem "modernizr", "2.5.3"
diff --git a/Gemfile.lock b/Gemfile.lock
index 100e88d0fd2..f9a0128f0e0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -199,6 +199,7 @@ GEM
httpauth (0.1)
i18n (0.6.1)
journey (1.0.4)
+ jquery-atwho-rails (0.1.6)
jquery-rails (2.0.2)
railties (>= 3.2.0, < 5.0)
thor (~> 0.14)
@@ -441,6 +442,7 @@ DEPENDENCIES
haml-rails
headless
httparty
+ jquery-atwho-rails (= 0.1.6)
jquery-rails (= 2.0.2)
jquery-ui-rails (= 0.5.0)
kaminari
diff --git a/Guardfile b/Guardfile
index 50a10af9a31..e682f0b6cf1 100644
--- a/Guardfile
+++ b/Guardfile
@@ -4,6 +4,7 @@
guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch(%r{^lib/api/(.+)\.rb$}) { |m| "spec/requests/api/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
# Rails example
diff --git a/VERSION b/VERSION
index a564e65383b..dedcc7d4335 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.9.0pre
+2.9.1
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index f9fdb0f7dc2..02ef6caba38 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -11,6 +11,7 @@
//= require jquery.endless-scroll
//= require jquery.highlight
//= require jquery.waitforimages
+//= require jquery.atwho
//= require bootstrap
//= require modernizr
//= require chosen-jquery
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 92d542a9866..424ba71f7cb 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -4,6 +4,7 @@
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.all
*= require jquery.ui.aristo
+ *= require jquery.atwho
*= require chosen
*= require_self
*= require main
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index c5b37916086..f13a1d6d196 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -185,36 +185,6 @@ span.update-author {
}
}
-.event_label {
- @extend .label;
- background-color: #999;
-
- &.pushed {
- background-color: #4A97BD;
- }
-
- &.opened {
- background-color: #469847;
- }
-
- &.closed {
- background-color: #B94A48;
- }
-
- &.merged {
- background-color: #2A2;
- }
-
- &.joined {
- background-color: #1ca9dd;
- }
-
- &.left {
- background-color: #888;
- float:none;
- }
-}
-
form {
@extend .form-horizontal;
@@ -355,41 +325,6 @@ p.time {
border:2px solid #ddd;
}
-.event_feed {
- min-height:40px;
- border-bottom:1px solid #ddd;
- .avatar {
- width:32px;
- }
- .event_icon {
- float:right;
- margin-right:2px;
- img {
- width:20px;
- }
- }
- ul {
- margin-left:50px;
- margin-bottom:5px;
- .avatar {
- width:24px;
- }
- }
-
- padding: 15px 5px;
- &:last-child { border:none }
- .wll:hover { background:none }
-
- .event_commits {
- margin-top: 5px;
-
- li.commit {
- background: transparent;
- padding:5px;
- border:none;
- }
- }
-}
.ico {
background: url("images.png") no-repeat -85px -77px;
@@ -639,22 +574,6 @@ li.note {
background:#fff;
}
-/**
- * Push event widget
- *
- */
-.event_lp {
- @extend .ui-box;
- color:#777;
- margin-bottom:20px;
- padding:8px;
- @include border-radius(4px);
- min-height:22px;
-
- .avatar {
- width:24px;
- }
-}
.supp_diff_link,
.mr_show_all_commits {
diff --git a/app/assets/stylesheets/gitlab_bootstrap/lists.scss b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
index 402ba04bd00..5585c35c089 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/lists.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
@@ -1,6 +1,6 @@
/** LISTS **/
-ul {
+ul {
/**
* List li block element #1
*
@@ -18,7 +18,7 @@ ul {
.author { color: #999; }
p {
- padding-top:5px;
+ padding-top:5px;
margin:0;
color:#222;
img {
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index 75001d3a7c3..14b289c0a5d 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -143,6 +143,7 @@ $hover: #fdf5d9;
@import "sections/projects.scss";
@import "sections/merge_requests.scss";
@import "sections/graph.scss";
+@import "sections/events.scss";
/**
* This scss file redefine chozen selectbox styles for
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 75e38aeea93..33b051351f3 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -1,7 +1,7 @@
.commit-box {
@extend .main_box;
- .commit-head {
+ .commit-head {
@extend .top_box_content;
.commit-title {
@@ -29,11 +29,11 @@
.sha-block {
text-align:right;
- &:first-child {
+ &:first-child {
padding-bottom:6px;
}
- a {
+ a {
border-bottom: 1px solid #aaa;
margin-left: 9px;
}
@@ -54,7 +54,7 @@
}
/**
- *
+ *
* COMMIT SHOw
*
*/
@@ -71,7 +71,7 @@
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
- span {
+ span {
font-size:14px;
}
}
@@ -111,8 +111,8 @@
}
}
- &.img_compared {
- img {
+ &.img_compared {
+ img {
max-width:300px;
}
}
@@ -120,12 +120,12 @@
}
.diff_file_content{
- table {
+ table {
border:none;
margin:0px;
padding:0px;
tr {
- td {
+ td {
font-size:12px;
}
}
@@ -145,29 +145,29 @@
moz-user-select: none;
-khtml-user-select: none;
user-select: none;
- a {
+ a {
float:left;
width:35px;
font-weight:normal;
color:#666;
- &:hover {
+ &:hover {
text-decoration:underline;
}
}
}
- .line_content {
- white-space:pre;
+ .line_content {
+ white-space:pre;
height:14px;
margin:0px;
padding:0px;
border:none;
- &.new {
+ &.new {
background: #CFD;
}
- &.old {
+ &.old {
background: #FDD;
}
- &.matched {
+ &.matched {
color:#ccc;
background:#fafafa;
}
@@ -182,32 +182,32 @@
/** COMMIT ROW **/
-.commit {
+.commit {
@extend .wll;
- .browse_code_link_holder {
+ .browse_code_link_holder {
@extend .span2;
float:right;
}
- .committed_ago {
+ .committed_ago {
float:right;
@extend .cgray;
}
- code {
+ code {
background:#FCEEC1;
color:$style_color;
}
- .commit_short_id {
+ .commit_short_id {
float:left;
@extend .lined;
min-width:65px;
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
}
-
- .commit-author-name {
+
+ .commit-author-name {
color: #777;
}
}
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
new file mode 100644
index 00000000000..db034e25bb5
--- /dev/null
+++ b/app/assets/stylesheets/sections/events.scss
@@ -0,0 +1,118 @@
+/**
+ * Events labels
+ *
+ */
+.event_label {
+ &.pushed {
+ padding:0 2px;
+ @extend .alert;
+ @extend .alert-info;
+ }
+
+ &.opened {
+ padding:0 2px;
+ @extend .alert;
+ @extend .alert-success;
+ }
+
+ &.closed {
+ padding:0 2px;
+ @extend .alert;
+ @extend .alert-error;
+ }
+
+ &.merged {
+ padding:0 2px;
+ @extend .alert;
+ @extend .alert-success;
+ }
+
+ &.left,
+ &.joined {
+ padding:0 2px;
+ @extend .alert;
+ }
+}
+
+/**
+ * Dashboard events feed
+ *
+ */
+.event-item {
+ min-height:40px;
+ border-bottom:1px solid #eee;
+ .event-title {
+ color:#333;
+ font-weight: bold;
+ .author_name {
+ color:#333;
+ }
+ }
+ .event-body {
+ p {
+ color:#555;
+ }
+ .event-info {
+ color:#666;
+ }
+ }
+ .avatar {
+ width:32px;
+ }
+ .event_icon {
+ float: right;
+ border: 1px solid #EEE;
+ padding: 5px;
+ @include border-radius(5px);
+ background: #F9F9F9;
+ img {
+ width:20px;
+ }
+ }
+ ul {
+ margin-left:50px;
+ margin-bottom:5px;
+ .avatar {
+ width:18px;
+ margin-top:3px;
+ }
+ }
+
+ padding: 15px 5px;
+ &:last-child { border:none }
+ .wll:hover { background:none }
+
+ .event_commits {
+ margin-top: 5px;
+
+ li {
+ &.commit {
+ background: transparent;
+ padding:3px;
+ border:none;
+ font-size:12px;
+ }
+ &.commits-stat {
+ display: block;
+ margin-top: 5px;
+ }
+ }
+ }
+}
+
+/**
+ * Push event widget
+ *
+ */
+.event_lp {
+ @extend .ui-box;
+ color:#777;
+ margin-bottom:20px;
+ padding:8px;
+ @include border-radius(4px);
+ min-height:22px;
+
+ .avatar {
+ width:24px;
+ }
+}
diff --git a/app/assets/stylesheets/sections/notes.scss b/app/assets/stylesheets/sections/notes.scss
index 267a9b4356c..d24d070df1e 100644
--- a/app/assets/stylesheets/sections/notes.scss
+++ b/app/assets/stylesheets/sections/notes.scss
@@ -43,7 +43,9 @@
padding: 8px 0;
overflow: hidden;
display: block;
+ position:relative;
img {float: left; margin-right: 10px;}
+ img.emoji {float:none;margin:0;}
.note-author cite{font-style: italic;}
p { color:$style_color; }
.note-author { color: $style_color;}
@@ -55,7 +57,9 @@
.delete-note {
display:none;
- float:right;
+ position:absolute;
+ right:0;
+ top:0;
}
&:hover {
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index e2d61864076..c9586ad5da9 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -30,7 +30,7 @@ class Admin::UsersController < AdminController
def new
- @admin_user = User.new(projects_limit: Gitlab.config.default_projects_limit)
+ @admin_user = User.new({ projects_limit: Gitlab.config.default_projects_limit }, as: :admin)
end
def edit
@@ -60,7 +60,7 @@ class Admin::UsersController < AdminController
def create
admin = params[:user].delete("admin")
- @admin_user = User.new(params[:user])
+ @admin_user = User.new(params[:user], as: :admin)
@admin_user.admin = (admin && admin.to_i > 0)
respond_to do |format|
@@ -86,7 +86,7 @@ class Admin::UsersController < AdminController
@admin_user.admin = (admin && admin.to_i > 0)
respond_to do |format|
- if @admin_user.update_attributes(params[:user])
+ if @admin_user.update_attributes(params[:user], as: :admin)
format.html { redirect_to [:admin, @admin_user], notice: 'User was successfully updated.' }
format.json { head :ok }
else
diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb
index 6d3f1aea6c9..1e7aec005f1 100644
--- a/app/controllers/commits_controller.rb
+++ b/app/controllers/commits_controller.rb
@@ -52,6 +52,7 @@ class CommitsController < ApplicationController
@commits = result[:commits]
@commit = result[:commit]
@diffs = result[:diffs]
+ @refs_are_same = result[:same]
@line_notes = []
@commits = CommitDecorator.decorate(@commits)
diff --git a/app/controllers/hooks_controller.rb b/app/controllers/hooks_controller.rb
index c81e6b05cb3..4359e99668f 100644
--- a/app/controllers/hooks_controller.rb
+++ b/app/controllers/hooks_controller.rb
@@ -1,5 +1,4 @@
class HooksController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
layout "project"
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 1d78a6d9b80..ceeee0096ab 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -1,5 +1,4 @@
class IssuesController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
before_filter :module_enabled
before_filter :issue, only: [:edit, :update, :destroy, :show]
diff --git a/app/controllers/labels_controller.rb b/app/controllers/labels_controller.rb
index e703f822982..189d8d9866d 100644
--- a/app/controllers/labels_controller.rb
+++ b/app/controllers/labels_controller.rb
@@ -1,5 +1,4 @@
class LabelsController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
before_filter :module_enabled
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index 187bb407b2d..1d0da43f7c7 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -1,5 +1,4 @@
class MergeRequestsController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
before_filter :module_enabled
before_filter :merge_request, only: [:edit, :update, :destroy, :show, :commits, :diffs, :automerge, :automerge_check, :raw]
diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb
index 10f089f138b..e8dbc8e49f1 100644
--- a/app/controllers/milestones_controller.rb
+++ b/app/controllers/milestones_controller.rb
@@ -1,5 +1,4 @@
class MilestonesController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
before_filter :module_enabled
before_filter :milestone, only: [:edit, :update, :destroy, :show]
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index f852e425891..b00c9283694 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -1,5 +1,4 @@
class SnippetsController < ApplicationController
- before_filter :authenticate_user!
before_filter :project
before_filter :snippet, only: [:show, :edit, :destroy, :update, :raw]
layout "project"
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index a5d5c742230..2b7265ca19e 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -32,7 +32,11 @@ module TreeHelper
#
# Returns boolean
def markup?(filename)
- filename.end_with?(*%w(.mdown .md .markdown .textile .rdoc .org .creole
- .mediawiki .rst .asciidoc .pod))
+ filename.end_with?(*%w(.textile .rdoc .org .creole
+ .mediawiki .rst .asciidoc .pod))
+ end
+
+ def gitlab_markdown?(filename)
+ filename.end_with?(*%w(.mdown .md .markdown))
end
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 15afedcb101..73583e9e7b7 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -82,20 +82,24 @@ class Commit
end
def compare(project, from, to)
- first = project.commit(to.try(:strip))
- last = project.commit(from.try(:strip))
-
result = {
commits: [],
diffs: [],
- commit: nil
+ commit: nil,
+ same: false
}
+ return result unless from && to
+
+ first = project.commit(to.try(:strip))
+ last = project.commit(from.try(:strip))
+
if first && last
commits = [first, last].sort_by(&:created_at)
younger = commits.first
older = commits.last
+ result[:same] = (younger.id == older.id)
result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
result[:commit] = Commit.new(older)
diff --git a/app/models/event.rb b/app/models/event.rb
index b11b21bda3b..dc76b6fd022 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -132,6 +132,7 @@ class Event < ActiveRecord::Base
end
end
+
delegate :name, :email, to: :author, prefix: true, allow_nil: true
delegate :title, to: :issue, prefix: true, allow_nil: true
delegate :title, to: :merge_request, prefix: true, allow_nil: true
diff --git a/app/models/user.rb b/app/models/user.rb
index 47876722755..a8626cc187a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -6,8 +6,9 @@ class User < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio,
- :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme,
- :theme_id, :force_random_password, :extern_uid, :provider
+ :name, :skype, :linkedin, :twitter, :dark_scheme,
+ :theme_id, :force_random_password, :extern_uid, :provider, :as => [:default, :admin]
+ attr_accessible :projects_limit, :as => :admin
attr_accessor :force_random_password
diff --git a/app/roles/repository.rb b/app/roles/repository.rb
index a77de4ad5f0..01156ac18b7 100644
--- a/app/roles/repository.rb
+++ b/app/roles/repository.rb
@@ -79,6 +79,14 @@ module Repository
@heads ||= repo.heads
end
+ def branches_names
+ heads.map(&:name)
+ end
+
+ def ref_names
+ [branches_names + tags].flatten
+ end
+
def tree(fcommit, path = nil)
fcommit = commit if fcommit == :head
tree = fcommit.tree
diff --git a/app/views/commits/compare.html.haml b/app/views/commits/compare.html.haml
index 7dab1f5c0fa..db15ba53823 100644
--- a/app/views/commits/compare.html.haml
+++ b/app/views/commits/compare.html.haml
@@ -1,16 +1,16 @@
= render "head"
-%h3
+%h3.page_title
Compare View
%hr
%div
- %p
+ %p.slead
Fill input field with commit id like
- %code '4eedf23'
+ %code.label_branch 4eedf23
or branch/tag name like
- %code master
- &amp; press compare button for commits list, code diff.
+ %code.label_branch master
+ and press compare button for commits list, code diff.
%br
@@ -19,22 +19,24 @@
= text_field_tag :from, params[:from], placeholder: "master", class: "xlarge"
= "..."
= text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
+ - if @refs_are_same
+ .alert
+ %span Refs are the same
.actions
- = submit_tag "Compare", class: "btn primary"
+ = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
-
-- unless @commits.empty?
+- if @commits.present?
%div.ui-box
%h5.small Commits (#{@commits.count})
%ul.unstyled= render @commits
-- unless @diffs.empty?
- %h4 Diff
- = render "commits/diffs", diffs: @diffs
+ - unless @diffs.empty?
+ %h4 Diff
+ = render "commits/diffs", diffs: @diffs
:javascript
$(function() {
- var availableTags = #{@project.heads.map(&:name).to_json};
+ var availableTags = #{@project.ref_names.to_json};
$("#from").autocomplete({
source: availableTags,
@@ -45,5 +47,7 @@
source: availableTags,
minLength: 1
});
+
+ disableButtonIfEmptyField('#to', '.commits-compare-btn');
});
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index cb25d831bca..ed4f33c0187 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -2,7 +2,7 @@
%li.commit
%p
= link_to commit.short_id(8), project_commit_path(project, id: commit.id), class: "commit_short_id"
- %strong.cdark= commit.author_name
+ %span= commit.author_name
&ndash;
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
= gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding"
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 7bae8db13f7..716a214b9bf 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,17 +1,18 @@
- if event.allowed?
- - if event.issue?
- .event_feed
+ %div.event-item
+ - if event.issue?
= render "events/event_issue", event: event
- - elsif event.merge_request?
- .event_feed
+ - elsif event.merge_request?
= render "events/event_merge_request", event: event
- - elsif event.push?
- .event_feed
+ - elsif event.push?
= render "events/event_push", event: event
- - elsif event.membership_changed?
- .event_feed
+ - elsif event.membership_changed?
= render "events/event_membership_changed", event: event
+ %span.cgray.right
+ = time_ago_in_words(event.created_at)
+ ago.
+ .clearfix
diff --git a/app/views/events/_event_issue.html.haml b/app/views/events/_event_issue.html.haml
index 4d357b7f912..60e82c4d4dc 100644
--- a/app/views/events/_event_issue.html.haml
+++ b/app/views/events/_event_issue.html.haml
@@ -1,11 +1,8 @@
= image_tag gravatar_icon(event.author_email), class: "avatar"
-%strong #{event.author_name}
-%span.event_label{class: event.action_name}= event.action_name
-issue
-= link_to project_issue_path(event.project, event.issue) do
- %strong= truncate event.issue_title
-at
-%strong= link_to event.project.name, event.project
-%span.cgray
- = time_ago_in_words(event.created_at)
- ago.
+.event-title
+ %strong.author_name #{event.author_name}
+ %span.event_label{class: event.action_name} #{event.action_name} issue
+ = link_to project_issue_path(event.project, event.issue) do
+ %strong= truncate event.issue_title
+ at
+ %strong= link_to event.project.name, event.project
diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml
index aa1d28f2be3..81b9994cff5 100644
--- a/app/views/events/_event_last_push.html.haml
+++ b/app/views/events/_event_last_push.html.haml
@@ -2,7 +2,7 @@
.event_lp
%div
= image_tag gravatar_icon(event.author_email), class: "avatar"
- %span Your pushed to
+ %span You pushed to
= event.ref_type
= link_to project_commits_path(event.project, ref: event.ref_name) do
%strong= truncate(event.ref_name, length: 28)
diff --git a/app/views/events/_event_membership_changed.html.haml b/app/views/events/_event_membership_changed.html.haml
index 464f24b3f03..e89065b91ef 100644
--- a/app/views/events/_event_membership_changed.html.haml
+++ b/app/views/events/_event_membership_changed.html.haml
@@ -1,9 +1,9 @@
= image_tag gravatar_icon(event.author_email), class: "avatar"
-%strong #{event.author_name}
-%span.event_label{class: event.action_name}= event.action_name
-project
-%strong= link_to event.project_name, event.project
-%span.cgray
- = time_ago_in_words(event.created_at)
- ago.
+.event-title
+ %strong.author_name #{event.author_name}
+ %span.event_label{class: event.action_name} #{event.action_name} project
+ %strong= link_to event.project_name, event.project
+ %span.cgray
+ = time_ago_in_words(event.created_at)
+ ago.
diff --git a/app/views/events/_event_merge_request.html.haml b/app/views/events/_event_merge_request.html.haml
index ceb39371a3a..655337f3480 100644
--- a/app/views/events/_event_merge_request.html.haml
+++ b/app/views/events/_event_merge_request.html.haml
@@ -1,18 +1,16 @@
- if event.action_name == "merged"
.event_icon= image_tag "event_mr_merged.png"
= image_tag gravatar_icon(event.author_email), class: "avatar"
-%strong #{event.author_name}
-%span.event_label{class: event.action_name}= event.action_name
-merge request
-= link_to project_merge_request_path(event.project, event.merge_request) do
- %strong= truncate event.merge_request_title
-at
-%strong= link_to event.project.name, event.project
-%span.cgray
- = time_ago_in_words(event.created_at)
- ago.
-%br
-%span= event.merge_request.source_branch
-&rarr;
-%span= event.merge_request.target_branch
+.event-title
+ %strong.author_name #{event.author_name}
+ %span.event_label{class: event.action_name} #{event.action_name} merge request
+ = link_to project_merge_request_path(event.project, event.merge_request) do
+ %strong= truncate event.merge_request_title
+ at
+ %strong= link_to event.project.name, event.project
+.event-body
+ .event-info
+ %span= event.merge_request.source_branch
+ &rarr;
+ %span= event.merge_request.target_branch
diff --git a/app/views/events/_event_push.html.haml b/app/views/events/_event_push.html.haml
index 0adcaf9d10e..c0be9cf5230 100644
--- a/app/views/events/_event_push.html.haml
+++ b/app/views/events/_event_push.html.haml
@@ -1,30 +1,26 @@
%div
.event_icon= image_tag "event_push.png"
= image_tag gravatar_icon(event.author_email), class: "avatar"
- %strong #{event.author_name}
- %span.event_label.pushed= event.push_action_name
- = event.ref_type
- = link_to project_commits_path(event.project, ref: event.ref_name) do
- %strong= event.ref_name
- at
- %strong= link_to event.project.name, event.project
- %span.cgray
- = time_ago_in_words(event.created_at)
- ago.
+
+ .event-title
+ %strong.author_name #{event.author_name}
+ %span.event_label.pushed #{event.push_action_name} #{event.ref_type}
+ = link_to project_commits_path(event.project, ref: event.ref_name) do
+ %strong= event.ref_name
+ at
+ %strong= link_to event.project.name, event.project
- if event.push_with_commits?
- - if event.commits_count > 1
- = link_to compare_project_commits_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do
- %strong #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]}
- project = event.project
- %ul.unstyled.event_commits
- - if event.commits_count > 3
- - event.commits[0...2].each do |commit|
- = render "events/commit", commit: commit, project: project
- %li
- %br
- \... and #{event.commits_count - 2} more commits
- - else
- - event.commits.each do |commit|
+ .event-body
+ %ul.unstyled.event_commits
+ - few_commits = event.commits[0...2]
+ - few_commits.each do |commit|
= render "events/commit", commit: commit, project: project
+ %li.commits-stat
+ - if event.commits_count > 2
+ %span ... and #{event.commits_count - 2} more commits.
+ = link_to compare_project_commits_path(event.project, from: event.parent_commit.id, to: event.last_commit.id) do
+ %strong Compare &rarr; #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]}
+ .clearfix
diff --git a/app/views/help/api.html.haml b/app/views/help/api.html.haml
index 35176f8e214..00085166bcf 100644
--- a/app/views/help/api.html.haml
+++ b/app/views/help/api.html.haml
@@ -1,77 +1,96 @@
-%h3 API
+%h3.page_title API
.back_link
= link_to help_path do
&larr; to index
-%hr
+%br
-%ol
+%ul.nav.nav-tabs.log-tabs
+ %li.active
+ = link_to "README", "#README", 'data-toggle' => 'tab'
%li
- %a{href: "#README"} README
+ = link_to "Projects", "#projects", 'data-toggle' => 'tab'
%li
- %a{href: "#projects"} Projects
+ = link_to "Snippets", "#snippets", 'data-toggle' => 'tab'
%li
- %a{href: "#snippets"} Snippets
+ = link_to "Repositories", "#repositories", 'data-toggle' => 'tab'
%li
- %a{href: "#users"} Users
+ = link_to "Users", "#users", 'data-toggle' => 'tab'
%li
- %a{href: "#issues"} Issues
+ = link_to "Session", "#session", 'data-toggle' => 'tab'
%li
- %a{href: "#milestones"} Milestones
-
-.file_holder#README
- .file_title
- %i.icon-file
- README
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "README.md"))
-
-%br
-
-.file_holder#projects
- .file_title
- %i.icon-file
- Projects
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
+ = link_to "Issues", "#issues", 'data-toggle' => 'tab'
+ %li
+ = link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
-%br
+.tab-content
+ .tab-pane.active#README
+ .file_holder
+ .file_title
+ %i.icon-file
+ README
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "README.md"))
-.file_holder#snippets
- .file_title
- %i.icon-file
- Projects Snippets
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
+ .tab-pane#projects
+ .file_holder
+ .file_title
+ %i.icon-file
+ Projects
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "projects.md"))
-%br
+ .tab-pane#snippets
+ .file_holder
+ .file_title
+ %i.icon-file
+ Projects Snippets
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
-.file_holder#users
- .file_title
- %i.icon-file
- Users
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "users.md"))
+ .tab-pane#repositories
+ .file_holder
+ .file_title
+ %i.icon-file
+ Projects
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "repositories.md"))
-%br
+ .tab-pane#users
+ .file_holder
+ .file_title
+ %i.icon-file
+ Users
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "users.md"))
-.file_holder#issues
- .file_title
- %i.icon-file
- Issues
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
+ .tab-pane#session
+ .file_holder
+ .file_title
+ %i.icon-file
+ Session
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "session.md"))
-%br
+ .tab-pane#issues
+ .file_holder
+ .file_title
+ %i.icon-file
+ Issues
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
-.file_holder#milestones
- .file_title
- %i.icon-file
- Milestones
- .file_content.wiki
- = preserve do
- = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
+ .tab-pane#milestones
+ .file_holder
+ .file_title
+ %i.icon-file
+ Milestones
+ .file_content.wiki
+ = preserve do
+ = markdown File.read(Rails.root.join("doc", "api", "milestones.md"))
diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml
index fc6e3c7ee6e..626a448c229 100644
--- a/app/views/notes/_common_form.html.haml
+++ b/app/views/notes/_common_form.html.haml
@@ -37,3 +37,14 @@
= f.file_field :attachment, class: "input-file"
%span.hint Any file less than 10 MB
+:javascript
+ $(function(){
+ var names = #{@project.users.pluck(:name)}, emoji = ['+1', '-1'];
+ var emoji = $.map(emoji, function(value, i) {return {key:value + ':', name:value}});
+ $('#note_note').
+ atWho('@', { data: names }).
+ atWho(':', {
+ data: emoji,
+ tpl: "<li data-value='${key}'>${name} #{escape_javascript image_tag('emoji/${name}.png', :size => '20x20')}</li>"
+ });
+ });
diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml
index ec6dba4ee07..55078718b79 100644
--- a/app/views/refs/_tree.html.haml
+++ b/app/views/refs/_tree.html.haml
@@ -43,7 +43,11 @@
%i.icon-file
= content.name
.file_content.wiki
- = raw GitHub::Markup.render(content.name, content.data)
+ - if gitlab_markdown?(content.name)
+ = preserve do
+ = markdown(content.data)
+ - else
+ = raw GitHub::Markup.render(content.name, content.data)
:javascript
$(function(){
diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml
index f6566ccf5d5..76173e24246 100644
--- a/app/views/refs/_tree_file.html.haml
+++ b/app/views/refs/_tree_file.html.haml
@@ -9,7 +9,11 @@
= link_to "history", project_commits_path(@project, path: params[:path], ref: @ref), class: "btn very_small"
= link_to "blame", blame_file_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small"
- if file.text?
- - if markup?(name)
+ - if gitlab_markdown?(name)
+ .file_content.wiki
+ = preserve do
+ = markdown(file.data)
+ - elsif markup?(name)
.file_content.wiki
= raw GitHub::Markup.render(name, file.data)
- else
diff --git a/config/initializers/4_resque.rb b/config/initializers/4_resque.rb
new file mode 100644
index 00000000000..2a5721ec742
--- /dev/null
+++ b/config/initializers/4_resque.rb
@@ -0,0 +1,31 @@
+# Custom Redis configuration
+rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
+rails_env = ENV['RAILS_ENV'] || 'development'
+config_file = File.join(rails_root, 'config', 'resque.yml')
+
+if File.exists?(config_file)
+ resque_config = YAML.load_file(config_file)
+ Resque.redis = resque_config[rails_env]
+end
+
+# Queues
+Resque.watch_queue(PostReceive.instance_variable_get("@queue"))
+
+# Authentication
+require 'resque/server'
+class Authentication
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ account = env['warden'].authenticate!(:database_authenticatable, :rememberable, scope: :user)
+ raise "Access denied" if !account.admin?
+ @app.call(env)
+ end
+end
+
+Resque::Server.use Authentication
+
+# Mailer
+Resque::Mailer.excluded_environments = []
diff --git a/config/initializers/4_resque_queues.rb b/config/initializers/4_resque_queues.rb
deleted file mode 100644
index 5b0087ab025..00000000000
--- a/config/initializers/4_resque_queues.rb
+++ /dev/null
@@ -1 +0,0 @@
-Resque.watch_queue(PostReceive.instance_variable_get("@queue"))
diff --git a/config/initializers/resque.rb b/config/initializers/resque.rb
deleted file mode 100644
index b333ceeea1a..00000000000
--- a/config/initializers/resque.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
-rails_env = ENV['RAILS_ENV'] || 'development'
-config_file = File.join(rails_root, 'config', 'resque.yml')
-
-if File.exists?(config_file)
- resque_config = YAML.load_file(config_file)
- Resque.redis = resque_config[rails_env]
-end
diff --git a/config/initializers/resque_authentication.rb b/config/initializers/resque_authentication.rb
deleted file mode 100644
index a439d322804..00000000000
--- a/config/initializers/resque_authentication.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require 'resque/server'
-class Authentication
- def initialize(app)
- @app = app
- end
-
- def call(env)
- account = env['warden'].authenticate!(:database_authenticatable, :rememberable, scope: :user)
- raise "Access denied" if !account.admin?
- @app.call(env)
- end
-end
-
-Resque::Server.use Authentication \ No newline at end of file
diff --git a/config/initializers/resque_mailer.rb b/config/initializers/resque_mailer.rb
deleted file mode 100644
index cec9dec9d0e..00000000000
--- a/config/initializers/resque_mailer.rb
+++ /dev/null
@@ -1 +0,0 @@
-Resque::Mailer.excluded_environments = []
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 23746d255b4..425dbf33f86 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -6,7 +6,7 @@ working_directory app_dir
# worker spawn times
preload_app true
-# nuke workers after 60 seconds (the default)
+# nuke workers after 30 seconds (60 is the default)
timeout 30
# listen on a Unix domain socket and/or a TCP port,
diff --git a/doc/api/README.md b/doc/api/README.md
index 9741072c095..36a36f8f6a4 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -30,8 +30,9 @@ When listing resources you can pass the following parameters:
## Contents
+ [Users](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/users.md)
++ [Session](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/session.md)
+ [Projects](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/projects.md)
+ [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
++ [Repositories](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/repositories.md)
+ [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
+ [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md)
-+ [SSH Keys](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/keys.md)
diff --git a/doc/api/keys.md b/doc/api/keys.md
deleted file mode 100644
index d22b22e20b8..00000000000
--- a/doc/api/keys.md
+++ /dev/null
@@ -1,79 +0,0 @@
-## List keys
-
-Get a list of currently authenticated user's keys.
-
-```
-GET /keys
-```
-
-```json
-[
- {
- "id": 1,
- "title" : "Public key"
- "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
- 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
- soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
- },
- {
- "id": 3,
- "title" : "Another Public key"
- "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
- 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
- soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
- }
-]
-```
-
-## Single key
-
-Get a single key.
-
-```
-GET /keys/:id
-```
-
-Parameters:
-
-+ `id` (required) - The ID of a key
-
-```json
-{
- "id": 1,
- "title" : "Public key"
- "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
- 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
- soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
-}
-```
-## Add key
-
-Create new key owned by currently authenticated user
-
-```
-POST /keys
-```
-
-Parameters:
-
-+ `title` (required) - new SSH Key's title
-+ `key` (required) - new SSH key
-
-Will return created key with status `201 Created` on success, or `404 Not
-found` on fail.
-
-## Delete key
-
-Delete key owned by currently authenticated user
-
-```
-DELETE /keys/:id
-```
-
-Parameters:
-
-+ `id` (required) - key ID
-
-Will return `200 OK` on success, or `404 Not Found` on fail.
-
-
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 73d6adc9bc3..d06a41c2d74 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -102,7 +102,7 @@ Parameters:
+ `name` (required) - new project name
+ `code` (optional) - new project code, uses project name if not set
+ `path` (optional) - new project path, uses project name if not set
-+ `description (optional) - short project description
++ `description` (optional) - short project description
+ `default_branch` (optional) - 'master' by default
+ `issues_enabled` (optional) - enabled by default
+ `wall_enabled` (optional) - enabled by default
@@ -112,66 +112,89 @@ Parameters:
Will return created project with status `201 Created` on success, or `404 Not
found` on fail.
-## Get project users
+## List project team members
-Get users and access roles for existing project
+Get a list of project team members.
```
-GET /projects/:id/users
+GET /projects/:id/members
```
Parameters:
+ `id` (required) - The ID or code name of a project
-Will return users and their access roles with status `200 OK` on success, or `404 Not found` on fail.
+## Get project team member
-## Add project users
+Get a project team member.
-Add users to exiting project
+```
+GET /projects/:id/members/:user_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `user_id` (required) - The ID of a user
+```json
+{
+
+ "id": 1,
+ "email": "john@example.com",
+ "name": "John Smith",
+ "blocked": false,
+ "created_at": "2012-05-23T08:00:58Z",
+ "access_level": 40
+}
```
-POST /projects/:id/users
+
+## Add project team member
+
+Add a user to a project team.
+
+```
+POST /projects/:id/members
```
Parameters:
+ `id` (required) - The ID or code name of a project
-+ `user_ids` (required) - The ID list of users to add
-+ `project_access` (required) - Project access level
++ `user_id` (required) - The ID of a user to add
++ `access_level` (required) - Project access level
Will return status `201 Created` on success, or `404 Not found` on fail.
-## Update project users access level
+## Edit project team member
-Update existing users to specified access level
+Update project team member to specified access level.
```
-PUT /projects/:id/users
+PUT /projects/:id/members/:user_id
```
Parameters:
+ `id` (required) - The ID or code name of a project
-+ `user_ids` (required) - The ID list of users to add
-+ `project_access` (required) - Project access level
++ `user_id` (required) - The ID of a team member
++ `access_level` (required) - Project access level
Will return status `200 OK` on success, or `404 Not found` on fail.
-## Delete project users
+## Remove project team member
-Delete users from exiting project
+Removes user from project team.
```
-DELETE /projects/:id/users
+DELETE /projects/:id/members/:user_id
```
Parameters:
+ `id` (required) - The ID or code name of a project
-+ `user_ids` (required) - The ID list of users to add
++ `user_id` (required) - The ID of a team member
-Will return status `200 OK` on success, or `404 Not found` on fail.
+Status code `200` will be returned on success.
## Get project hooks
@@ -216,135 +239,3 @@ Parameters:
+ `hook_id` (required) - The ID of hook to delete
Will return status `200 OK` on success, or `404 Not found` on fail.
-
-## Project repository branches
-
-Get a list of repository branches from a project, sorted by name alphabetically.
-
-```
-GET /projects/:id/repository/branches
-```
-
-Parameters:
-
-+ `id` (required) - The ID or code name of a project
-
-```json
-[
- {
- "name": "master",
- "commit": {
- "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
- "parents": [
- {
- "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
- }
- ],
- "tree": "46e82de44b1061621357f24c05515327f2795a95",
- "message": "add projects API",
- "author": {
- "name": "John Smith",
- "email": "john@example.com"
- },
- "committer": {
- "name": "John Smith",
- "email": "john@example.com"
- },
- "authored_date": "2012-06-27T05:51:39-07:00",
- "committed_date": "2012-06-28T03:44:20-07:00"
- }
- }
-]
-```
-
-Get a single project repository branch.
-
-```
-GET /projects/:id/repository/branches/:branch
-```
-
-Parameters:
-
-+ `id` (required) - The ID or code name of a project
-+ `branch` (required) - The name of the branch
-
-```json
-{
- "name": "master",
- "commit": {
- "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
- "parents": [
- {
- "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
- }
- ],
- "tree": "46e82de44b1061621357f24c05515327f2795a95",
- "message": "add projects API",
- "author": {
- "name": "John Smith",
- "email": "john@example.com"
- },
- "committer": {
- "name": "John Smith",
- "email": "john@example.com"
- },
- "authored_date": "2012-06-27T05:51:39-07:00",
- "committed_date": "2012-06-28T03:44:20-07:00"
- }
-}
-```
-
-## Project repository tags
-
-Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
-
-```
-GET /projects/:id/repository/tags
-```
-
-Parameters:
-
-+ `id` (required) - The ID or code name of a project
-
-```json
-[
- {
- "name": "v1.0.0",
- "commit": {
- "id": "2695effb5807a22ff3d138d593fd856244e155e7",
- "parents": [
-
- ],
- "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d",
- "message": "Initial commit",
- "author": {
- "name": "John Smith",
- "email": "john@example.com"
- },
- "committer": {
- "name": "Jack Smith",
- "email": "jack@example.com"
- },
- "authored_date": "2012-05-28T04:42:42-07:00",
- "committed_date": "2012-05-28T04:42:42-07:00"
- }
- }
-]
-```
-
-## Raw blob content
-
-Get the raw file contents for a file.
-
-```
-GET /projects/:id/repository/commits/:sha/blob
-```
-
-Parameters:
-
-+ `id` (required) - The ID or code name of a project
-+ `sha` (required) - The commit or branch name
-+ `filepath` (required) - The path the file
-
-Will return the raw file contents.
-
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
new file mode 100644
index 00000000000..487ad9b2718
--- /dev/null
+++ b/doc/api/repositories.md
@@ -0,0 +1,166 @@
+## Project repository branches
+
+Get a list of repository branches from a project, sorted by name alphabetically.
+
+```
+GET /projects/:id/repository/branches
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+```json
+[
+ {
+ "name": "master",
+ "commit": {
+ "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "parents": [
+ {
+ "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+ }
+ ],
+ "tree": "46e82de44b1061621357f24c05515327f2795a95",
+ "message": "add projects API",
+ "author": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ },
+ "committer": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ },
+ "authored_date": "2012-06-27T05:51:39-07:00",
+ "committed_date": "2012-06-28T03:44:20-07:00"
+ }
+ }
+]
+```
+
+## Project repository branch
+
+Get a single project repository branch.
+
+```
+GET /projects/:id/repository/branches/:branch
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `branch` (required) - The name of the branch
+
+```json
+{
+ "name": "master",
+ "commit": {
+ "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c",
+ "parents": [
+ {
+ "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8"
+ }
+ ],
+ "tree": "46e82de44b1061621357f24c05515327f2795a95",
+ "message": "add projects API",
+ "author": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ },
+ "committer": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ },
+ "authored_date": "2012-06-27T05:51:39-07:00",
+ "committed_date": "2012-06-28T03:44:20-07:00"
+ }
+}
+```
+
+## Project repository tags
+
+Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
+
+```
+GET /projects/:id/repository/tags
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+```json
+[
+ {
+ "name": "v1.0.0",
+ "commit": {
+ "id": "2695effb5807a22ff3d138d593fd856244e155e7",
+ "parents": [
+
+ ],
+ "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d",
+ "message": "Initial commit",
+ "author": {
+ "name": "John Smith",
+ "email": "john@example.com"
+ },
+ "committer": {
+ "name": "Jack Smith",
+ "email": "jack@example.com"
+ },
+ "authored_date": "2012-05-28T04:42:42-07:00",
+ "committed_date": "2012-05-28T04:42:42-07:00"
+ }
+ }
+]
+```
+
+## Project repository commits
+
+Get a list of repository commits in a project.
+
+```
+GET /projects/:id/repository/commits
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `ref_name` (optional) - The name of a repository branch or tag
+
+```json
+[
+ {
+ "id": "ed899a2f4b50b4370feeea94676502b42383c746",
+ "short_id": "ed899a2f4b5",
+ "title": "Replace sanitize with escape once",
+ "author_name": "Dmitriy Zaporozhets",
+ "author_email": "dzaporozhets@sphereconsultinginc.com",
+ "created_at": "2012-09-20T11:50:22+03:00"
+ },
+ {
+ "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
+ "short_id": "6104942438c",
+ "title": "Sanitize for network graph",
+ "author_name": "randx",
+ "author_email": "dmitriy.zaporozhets@gmail.com",
+ "created_at": "2012-09-20T09:06:12+03:00"
+ }
+]
+```
+
+## Raw blob content
+
+Get the raw file contents for a file.
+
+```
+GET /projects/:id/repository/commits/:sha/blob
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `sha` (required) - The commit or branch name
++ `filepath` (required) - The path the file
+
+Will return the raw file contents.
diff --git a/doc/api/session.md b/doc/api/session.md
new file mode 100644
index 00000000000..9fdbeb439a4
--- /dev/null
+++ b/doc/api/session.md
@@ -0,0 +1,22 @@
+Login to get private token
+
+```
+POST /session
+```
+
+Parameters:
+
++ `email` (required) - The email of user
++ `password` (required) - Valid password
+
+
+```json
+{
+ "id": 1,
+ "email": "john@example.com",
+ "name": "John Smith",
+ "private_token": "dd34asd13as",
+ "created_at": "2012-05-23T08:00:58Z",
+ "blocked": true
+}
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index b9b04dc5399..4f806b145d1 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -88,3 +88,81 @@ GET /user
"theme_id": 1
}
```
+
+## List SSH keys
+
+Get a list of currently authenticated user's SSH keys.
+
+```
+GET /user/keys
+```
+
+```json
+[
+ {
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ },
+ {
+ "id": 3,
+ "title" : "Another Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+ }
+]
+```
+
+## Single SSH key
+
+Get a single key.
+
+```
+GET /user/keys/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of an SSH key
+
+```json
+{
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+}
+```
+## Add SSH key
+
+Create new key owned by currently authenticated user
+
+```
+POST /user/keys
+```
+
+Parameters:
+
++ `title` (required) - new SSH Key's title
++ `key` (required) - new SSH key
+
+Will return created key with status `201 Created` on success, or `404 Not
+found` on fail.
+
+## Delete SSH key
+
+Delete key owned by currently authenticated user
+
+```
+DELETE /user/keys/:id
+```
+
+Parameters:
+
++ `id` (required) - SSH key ID
+
+Will return `200 OK` on success, or `404 Not Found` on fail.
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index 6c603bbea55..154b97e34d3 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -16,7 +16,7 @@ class Dashboard < Spinach::FeatureSteps
end
Then 'I should see last push widget' do
- page.should have_content "Your pushed to branch new_design"
+ page.should have_content "You pushed to branch new_design"
page.should have_link "Create Merge Request"
end
diff --git a/lib/api.rb b/lib/api.rb
index 37e03849b96..2890a8cc9e8 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -17,6 +17,6 @@ module Gitlab
mount Projects
mount Issues
mount Milestones
- mount Keys
+ mount Session
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 13a48e12019..ee693de699e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -9,6 +9,10 @@ module Gitlab
expose :id, :email, :name, :blocked, :created_at
end
+ class UserLogin < UserBasic
+ expose :private_token
+ end
+
class Hook < Grape::Entity
expose :id, :url
end
@@ -20,15 +24,20 @@ module Gitlab
expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :created_at
end
- class UsersProject < Grape::Entity
- expose :user, using: Entities::UserBasic
- expose :project_access
+ class ProjectMember < UserBasic
+ expose :project_access, :as => :access_level do |user, options|
+ options[:project].users_projects.find_by_user_id(user.id).project_access
+ end
end
class RepoObject < Grape::Entity
expose :name, :commit
end
+ class RepoCommit < Grape::Entity
+ expose :id, :short_id, :title, :author_name, :author_email, :created_at
+ end
+
class ProjectSnippet < Grape::Entity
expose :id, :title, :file_name
expose :author, using: Entities::UserBasic
@@ -36,7 +45,9 @@ module Gitlab
end
class Milestone < Grape::Entity
- expose :id, :title, :description, :due_date, :closed, :updated_at, :created_at
+ expose :id
+ expose (:project_id) {|milestone| milestone.project.id}
+ expose :title, :description, :due_date, :closed, :updated_at, :created_at
end
class Issue < Grape::Entity
@@ -49,10 +60,8 @@ module Gitlab
expose :closed, :updated_at, :created_at
end
- class Key < Grape::Entity
- expose :id,
- :title,
- :key
+ class SSHKey < Grape::Entity
+ expose :id, :title, :key
end
end
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 9a08b995800..14390545bd5 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -61,7 +61,7 @@ module Gitlab
error!({'message' => message}, status)
end
- private
+ private
def abilities
@abilities ||= begin
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
deleted file mode 100644
index 4c302727c4f..00000000000
--- a/lib/api/keys.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-module Gitlab
- # Keys API
- class Keys < Grape::API
- before { authenticate! }
- resource :keys do
- # Get currently authenticated user's keys
- #
- # Example Request:
- # GET /keys
- get do
- present current_user.keys, with: Entities::Key
- end
- # Get single key owned by currently authenticated user
- #
- # Example Request:
- # GET /keys/:id
- get "/:id" do
- key = current_user.keys.find params[:id]
- present key, with: Entities::Key
- end
- # Add new ssh key to currently authenticated user
- #
- # Parameters:
- # key (required) - New SSH Key
- # title (required) - New SSH Key's title
- # Example Request:
- # POST /keys
- post do
- attrs = attributes_for_keys [:title, :key]
- key = current_user.keys.new attrs
- if key.save
- present key, with: Entities::Key
- else
- not_found!
- end
- end
- # Delete existed ssh key of currently authenticated user
- #
- # Parameters:
- # id (required) - SSH Key ID
- # Example Request:
- # DELETE /keys/:id
- delete "/:id" do
- key = current_user.keys.find params[:id]
- key.delete
- end
- end
- end
-end
-
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index daaff940325..f55dfd04cc5 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -11,6 +11,8 @@ module Gitlab
# Example Request:
# GET /projects/:id/milestones
get ":id/milestones" do
+ authorize! :read_milestone, user_project
+
present paginate(user_project.milestones), with: Entities::Milestone
end
@@ -22,6 +24,8 @@ module Gitlab
# Example Request:
# GET /projects/:id/milestones/:milestone_id
get ":id/milestones/:milestone_id" do
+ authorize! :read_milestone, user_project
+
@milestone = user_project.milestones.find(params[:milestone_id])
present @milestone, with: Entities::Milestone
end
@@ -36,6 +40,8 @@ module Gitlab
# Example Request:
# POST /projects/:id/milestones
post ":id/milestones" do
+ authorize! :admin_milestone, user_project
+
attrs = attributes_for_keys [:title, :description, :due_date]
@milestone = user_project.milestones.new attrs
if @milestone.save
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 1d9004f8eed..c3dc3da6fac 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -40,14 +40,14 @@ module Gitlab
post do
params[:code] ||= params[:name]
params[:path] ||= params[:name]
- attrs = attributes_for_keys [:code,
- :path,
- :name,
- :description,
- :default_branch,
- :issues_enabled,
- :wall_enabled,
- :merge_requests_enabled,
+ attrs = attributes_for_keys [:code,
+ :path,
+ :name,
+ :description,
+ :default_branch,
+ :issues_enabled,
+ :wall_enabled,
+ :merge_requests_enabled,
:wiki_enabled]
@project = Project.create_by_user(attrs, current_user)
if @project.saved?
@@ -57,56 +57,83 @@ module Gitlab
end
end
- # Get project users
+ # Get a project team members
#
# Parameters:
# id (required) - The ID or code name of a project
# Example Request:
- # GET /projects/:id/users
- get ":id/users" do
- @users_projects = paginate user_project.users_projects
- present @users_projects, with: Entities::UsersProject
+ # GET /projects/:id/members
+ get ":id/members" do
+ @members = paginate user_project.users
+ present @members, with: Entities::ProjectMember, project: user_project
end
- # Add users to project with specified access level
+ # Get a project team members
#
# Parameters:
# id (required) - The ID or code name of a project
- # user_ids (required) - The ID list of users to add
- # project_access (required) - Project access level
+ # user_id (required) - The ID of a user
# Example Request:
- # POST /projects/:id/users
- post ":id/users" do
+ # GET /projects/:id/members/:user_id
+ get ":id/members/:user_id" do
+ @member = user_project.users.find params[:user_id]
+ present @member, with: Entities::ProjectMember, project: user_project
+ end
+
+ # Add a new project team member
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # user_id (required) - The ID of a user
+ # access_level (required) - Project access level
+ # Example Request:
+ # POST /projects/:id/members
+ post ":id/members" do
authorize! :admin_project, user_project
- user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access])
- nil
+ users_project = user_project.users_projects.new(
+ user_id: params[:user_id],
+ project_access: params[:access_level]
+ )
+
+ if users_project.save
+ @member = users_project.user
+ present @member, with: Entities::ProjectMember, project: user_project
+ else
+ not_found!
+ end
end
- # Update users to specified access level
+ # Update project team member
#
# Parameters:
# id (required) - The ID or code name of a project
- # user_ids (required) - The ID list of users to add
- # project_access (required) - New project access level to
+ # user_id (required) - The ID of a team member
+ # access_level (required) - Project access level
# Example Request:
- # PUT /projects/:id/add_users
- put ":id/users" do
+ # PUT /projects/:id/members/:user_id
+ put ":id/members/:user_id" do
authorize! :admin_project, user_project
- user_project.update_users_ids_to_role(params[:user_ids].values, params[:project_access])
- nil
+ users_project = user_project.users_projects.find_by_user_id params[:user_id]
+
+ if users_project.update_attributes(project_access: params[:access_level])
+ @member = users_project.user
+ present @member, with: Entities::ProjectMember, project: user_project
+ else
+ not_found!
+ end
end
- # Delete project users
+ # Remove a team member from project
#
# Parameters:
# id (required) - The ID or code name of a project
- # user_ids (required) - The ID list of users to delete
+ # user_id (required) - The ID of a team member
# Example Request:
- # DELETE /projects/:id/users
- delete ":id/users" do
+ # DELETE /projects/:id/members/:user_id
+ delete ":id/members/:user_id" do
authorize! :admin_project, user_project
- user_project.delete_users_ids_from_team(params[:user_ids].values)
- nil
+ users_project = user_project.users_projects.find_by_user_id params[:user_id]
+ users_project.destroy
end
# Get project hooks
@@ -184,6 +211,24 @@ module Gitlab
present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
end
+ # Get a project repository commits
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # ref_name (optional) - The name of a repository branch or tag
+ # Example Request:
+ # GET /projects/:id/repository/commits
+ get ":id/repository/commits" do
+ authorize! :download_code, user_project
+
+ page = params[:page] || 0
+ per_page = params[:per_page] || 20
+ ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
+
+ commits = user_project.commits(ref, nil, per_page, page * per_page)
+ present CommitDecorator.decorate(commits), with: Entities::RepoCommit
+ end
+
# Get a project snippet
#
# Parameters:
@@ -207,6 +252,8 @@ module Gitlab
# Example Request:
# POST /projects/:id/snippets
post ":id/snippets" do
+ authorize! :write_snippet, user_project
+
attrs = attributes_for_keys [:title, :file_name]
attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
attrs[:content] = params[:code] if params[:code].present?
@@ -282,6 +329,8 @@ module Gitlab
# Example Request:
# GET /projects/:id/repository/commits/:sha/blob
get ":id/repository/commits/:sha/blob" do
+ authorize! :download_code, user_project
+
ref = params[:sha]
commit = user_project.commit ref
diff --git a/lib/api/session.rb b/lib/api/session.rb
new file mode 100644
index 00000000000..b4050160ae4
--- /dev/null
+++ b/lib/api/session.rb
@@ -0,0 +1,20 @@
+module Gitlab
+ # Users API
+ class Session < Grape::API
+ # Login to get token
+ #
+ # Example Request:
+ # POST /session
+ post "/session" do
+ resource = User.find_for_database_authentication(email: params[:email])
+
+ return unauthorized! unless resource
+
+ if resource.valid_password?(params[:password])
+ present resource, with: Entities::UserLogin
+ else
+ unauthorized!
+ end
+ end
+ end
+end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 98ced6f8e5b..0ca8fb2a1ae 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -25,12 +25,59 @@ module Gitlab
end
end
- # Get currently authenticated user
- #
- # Example Request:
- # GET /user
- get "/user" do
- present @current_user, with: Entities::User
+ resource :user do
+ # Get currently authenticated user
+ #
+ # Example Request:
+ # GET /user
+ get do
+ present @current_user, with: Entities::User
+ end
+
+ # Get currently authenticated user's keys
+ #
+ # Example Request:
+ # GET /user/keys
+ get "keys" do
+ present current_user.keys, with: Entities::SSHKey
+ end
+
+ # Get single key owned by currently authenticated user
+ #
+ # Example Request:
+ # GET /user/keys/:id
+ get "keys/:id" do
+ key = current_user.keys.find params[:id]
+ present key, with: Entities::SSHKey
+ end
+
+ # Add new ssh key to currently authenticated user
+ #
+ # Parameters:
+ # key (required) - New SSH Key
+ # title (required) - New SSH Key's title
+ # Example Request:
+ # POST /user/keys
+ post "keys" do
+ attrs = attributes_for_keys [:title, :key]
+ key = current_user.keys.new attrs
+ if key.save
+ present key, with: Entities::SSHKey
+ else
+ not_found!
+ end
+ end
+
+ # Delete existed ssh key of currently authenticated user
+ #
+ # Parameters:
+ # id (required) - SSH Key ID
+ # Example Request:
+ # DELETE /user/keys/:id
+ delete "keys/:id" do
+ key = current_user.keys.find params[:id]
+ key.delete
+ end
end
end
end
diff --git a/lib/gitlab/graph_commit.rb b/lib/gitlab/graph_commit.rb
index e14d670e5c7..d3668a99107 100644
--- a/lib/gitlab/graph_commit.rb
+++ b/lib/gitlab/graph_commit.rb
@@ -5,7 +5,7 @@ module Gitlab
attr_accessor :time, :space
attr_accessor :refs
- include ActionView::Helpers::SanitizeHelper
+ include ActionView::Helpers::TagHelper
def self.to_graph(project)
@repo = project.repo
@@ -166,7 +166,7 @@ module Gitlab
h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
h[:id] = sha
h[:date] = date
- h[:message] = sanitize(Gitlab::Encode.utf8(message))
+ h[:message] = escape_once(Gitlab::Encode.utf8(message))
h[:login] = author.email
h
end
diff --git a/lib/tasks/bulk_add_permission.rake b/lib/tasks/bulk_add_permission.rake
index 55797825e0c..bf08ace8e9c 100644
--- a/lib/tasks/bulk_add_permission.rake
+++ b/lib/tasks/bulk_add_permission.rake
@@ -1,26 +1,20 @@
-desc "Add all users to all projects, system administratos are added as masters"
+desc "Add all users to all projects (admin users are added as masters)"
task :add_users_to_project_teams => :environment do |t, args|
- users = User.find_all_by_admin(false, :select => 'id').map(&:id)
- admins = User.find_all_by_admin(true, :select => 'id').map(&:id)
+ user_ids = User.where(:admin => false).pluck(:id)
+ admin_ids = User.where(:admin => true).pluck(:id)
- users.each do |user|
- puts "#{user}"
- end
-
- Project.all.each do |project|
- puts "Importing #{users.length} users into #{project.path}"
- UsersProject.bulk_import(project, users, UsersProject::DEVELOPER)
- puts "Importing #{admins.length} admins into #{project.path}"
- UsersProject.bulk_import(project, admins, UsersProject::MASTER)
+ Project.find_each do |project|
+ puts "Importing #{user_ids.size} users into #{project.code}"
+ UsersProject.bulk_import(project, user_ids, UsersProject::DEVELOPER)
+ puts "Importing #{admin_ids.size} admins into #{project.code}"
+ UsersProject.bulk_import(project, admin_ids, UsersProject::MASTER)
end
end
desc "Add user to as a developer to all projects"
task :add_user_to_project_teams, [:email] => :environment do |t, args|
- user_email = args.email
- user = User.find_by_email(user_email)
-
- project_ids = Project.all.map(&:id)
+ user = User.find_by_email args.email
+ project_ids = Project.pluck(:id)
- UsersProject.user_bulk_import(user,project_ids,UsersProject::DEVELOPER)
+ UsersProject.user_bulk_import(user, project_ids, UsersProject::DEVELOPER)
end
diff --git a/lib/tasks/bulk_import.rake b/lib/tasks/bulk_import.rake
index edb4a599eb0..914f920a8d7 100644
--- a/lib/tasks/bulk_import.rake
+++ b/lib/tasks/bulk_import.rake
@@ -1,20 +1,17 @@
-
desc "Imports existing Git repos from a directory into new projects in git_base_path"
task :import_projects, [:directory,:email] => :environment do |t, args|
- user_email = args.email
- import_directory = args.directory
+ user_email, import_directory = args.email, args.directory
repos_to_import = Dir.glob("#{import_directory}/*")
git_base_path = Gitlab.config.git_base_path
- puts "Found #{repos_to_import.length} repos to import"
+ imported_count, skipped_count, failed_count = 0
+
+ puts "Found #{repos_to_import.size} repos to import"
- imported_count = 0
- skipped_count = 0
- failed_count = 0
repos_to_import.each do |repo_path|
repo_name = File.basename repo_path
+ clone_path = "#{git_base_path}#{repo_name}.git"
puts " Processing #{repo_name}"
- clone_path = "#{git_base_path}#{repo_name}.git"
if Dir.exists? clone_path
if Project.find_by_code(repo_name)
@@ -38,7 +35,6 @@ task :import_projects, [:directory,:email] => :environment do |t, args|
else
failed_count += 1
end
-
end
puts "Finished importing #{imported_count} projects (skipped #{skipped_count}, failed #{failed_count})."
@@ -49,63 +45,39 @@ def clone_bare_repo_as_git(existing_path, new_path)
git_user = Gitlab.config.ssh_user
begin
sh "sudo -u #{git_user} -i git clone --bare '#{existing_path}' #{new_path}"
- true
- rescue Exception=> msg
- puts " ERROR: Faild to clone #{existing_path} to #{new_path}"
- puts " Make sure #{git_user} can reach #{existing_path}"
- puts " Exception-MSG: #{msg}"
- false
+ rescue Exception => msg
+ puts " ERROR: Failed to clone #{existing_path} to #{new_path}"
+ puts " Make sure #{git_user} can reach #{existing_path}"
+ puts " Exception-MSG: #{msg}"
end
end
-# Creats a project in Gitlag given a @project_name@ to use (for name, web url, and code
-# url) and a @user_email@ that will be assigned as the owner of the project.
+# Creates a project in GitLab given a `project_name` to use
+# (for name, web url, and code url) and a `user_email` that will be
+# assigned as the owner of the project.
def create_repo_project(project_name, user_email)
- user = User.find_by_email(user_email)
- if user
+ if user = User.find_by_email(user_email)
# Using find_by_code since that's the most important identifer to be unique
if Project.find_by_code(project_name)
puts " INFO: Project #{project_name} already exists in Gitlab, skipping."
- false
else
- project = nil
- if Project.find_by_code(project_name)
- puts " ERROR: Project already exists #{project_name}"
- return false
- project = Project.find_by_code(project_name)
- else
- project = Project.create(
- name: project_name,
- code: project_name,
- path: project_name,
- owner: user,
- description: "Automatically created from Rake on #{Time.now.to_s}"
- )
- end
-
- unless project.valid?
- puts " ERROR: Failed to create project #{project} because #{project.errors.first}"
- return false
- end
-
- # Add user as admin for project
- project.users_projects.create!(
- :project_access => UsersProject::MASTER,
- :user => user
+ project = Project.create(
+ name: project_name,
+ code: project_name,
+ path: project_name,
+ owner: user,
+ description: "Automatically created from 'import_projects' rake task on #{Time.now}"
)
- # Per projects_controller.rb#37
- project.update_repository
-
if project.valid?
- true
+ # Add user as admin for project
+ project.users_projects.create!(:project_access => UsersProject::MASTER, :user => user)
+ project.update_repository
else
puts " ERROR: Failed to create project #{project} because #{project.errors.first}"
- false
end
end
else
- puts " ERROR: #{user_email} not found, skipping"
- false
+ puts " ERROR: user with #{user_email} not found, skipping"
end
end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 04d240f6b12..06d7cb65d64 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -2,22 +2,20 @@ require 'active_record/fixtures'
namespace :gitlab do
namespace :app do
-
- # Create backup of gitlab system
- desc "GITLAB | Create a backup of the gitlab system"
+ # Create backup of GitLab system
+ desc "GITLAB | Create a backup of the GitLab system"
task :backup_create => :environment do
-
Rake::Task["gitlab:app:db_dump"].invoke
Rake::Task["gitlab:app:repo_dump"].invoke
Dir.chdir(Gitlab.config.backup_path)
# saving additional informations
- s = Hash.new
- s["db_version"] = "#{ActiveRecord::Migrator.current_version}"
- s["backup_created_at"] = "#{Time.now}"
- s["gitlab_version"] = %x{git rev-parse HEAD}.gsub(/\n/,"")
- s["tar_version"] = %x{tar --version | head -1}.gsub(/\n/,"")
+ s = {}
+ s[:db_version] = "#{ActiveRecord::Migrator.current_version}"
+ s[:backup_created_at] = "#{Time.now}"
+ s[:gitlab_version] = %x{git rev-parse HEAD}.gsub(/\n/,"")
+ s[:tar_version] = %x{tar --version | head -1}.gsub(/\n/,"")
File.open("#{Gitlab.config.backup_path}/backup_information.yml", "w+") do |file|
file << s.to_yaml.gsub(/^---\n/,'')
@@ -32,7 +30,7 @@ namespace :gitlab do
end
# cleanup: remove tmp files
- print "Deletion of tmp directories..."
+ print "Deleting tmp directories..."
if Kernel.system("rm -rf repositories/ db/ backup_information.yml")
puts "[DONE]".green
else
@@ -52,26 +50,23 @@ namespace :gitlab do
else
puts "[SKIPPING]".yellow
end
-
end
-
- # Restore backup of gitlab system
+ # Restore backup of GitLab system
desc "GITLAB | Restore a previously created backup"
task :backup_restore => :environment do
-
Dir.chdir(Gitlab.config.backup_path)
# check for existing backups in the backup dir
file_list = Dir.glob("*_gitlab_backup.tar").each.map { |f| f.split(/_/).first.to_i }
- puts "no backup found" if file_list.count == 0
+ puts "no backups found" if file_list.count == 0
if file_list.count > 1 && ENV["BACKUP"].nil?
puts "Found more than one backup, please specify which one you want to restore:"
puts "rake gitlab:app:backup_restore BACKUP=timestamp_of_backup"
exit 1;
end
- tar_file = ENV["BACKUP"].nil? ? File.join(file_list.first.to_s + "_gitlab_backup.tar") : File.join(ENV["BACKUP"] + "_gitlab_backup.tar")
+ tar_file = ENV["BACKUP"].nil? ? File.join("#{file_list.first}_gitlab_backup.tar") : File.join(ENV["BACKUP"] + "_gitlab_backup.tar")
unless File.exists?(tar_file)
puts "The specified backup doesn't exist!"
@@ -102,16 +97,14 @@ namespace :gitlab do
Rake::Task["gitlab:app:repo_restore"].invoke
# cleanup: remove tmp files
- print "Deletion of tmp directories..."
+ print "Deleting tmp directories..."
if Kernel.system("rm -rf repositories/ db/ backup_information.yml")
puts "[DONE]".green
else
puts "[FAILED]".red
end
-
end
-
################################################################################
################################# invoked tasks ################################
@@ -121,7 +114,7 @@ namespace :gitlab do
backup_path_repo = File.join(Gitlab.config.backup_path, "repositories")
FileUtils.mkdir_p(backup_path_repo) until Dir.exists?(backup_path_repo)
puts "Dumping repositories:"
- project = Project.all.map { |n| [n.path,n.path_to_repo] }
+ project = Project.all.map { |n| [n.path, n.path_to_repo] }
project << ["gitolite-admin.git", File.join(File.dirname(project.first.second), "gitolite-admin.git")]
project.each do |project|
print "- Dumping repository #{project.first}... "
@@ -136,11 +129,11 @@ namespace :gitlab do
task :repo_restore => :environment do
backup_path_repo = File.join(Gitlab.config.backup_path, "repositories")
puts "Restoring repositories:"
- project = Project.all.map { |n| [n.path,n.path_to_repo] }
+ project = Project.all.map { |n| [n.path, n.path_to_repo] }
project << ["gitolite-admin.git", File.join(File.dirname(project.first.second), "gitolite-admin.git")]
project.each do |project|
print "- Restoring repository #{project.first}... "
- FileUtils.rm_rf(project.second) if File.dirname(project.second) # delet old stuff
+ FileUtils.rm_rf(project.second) if File.dirname(project.second) # delete old stuff
if Kernel.system("cd #{File.dirname(project.second)} > /dev/null 2>&1 && git clone --bare #{backup_path_repo}/#{project.first}.bundle #{project.first}.git > /dev/null 2>&1")
permission_commands = [
"sudo chmod -R g+rwX #{Gitlab.config.git_base_path}",
@@ -157,8 +150,9 @@ namespace :gitlab do
###################################### DB ######################################
task :db_dump => :environment do
- backup_path_db = File.join(Gitlab.config.backup_path, "db")
- FileUtils.mkdir_p(backup_path_db) until Dir.exists?(backup_path_db)
+ backup_path_db = File.join(Gitlab.config.backup_path, "db")
+ FileUtils.mkdir_p(backup_path_db) unless Dir.exists?(backup_path_db)
+
puts "Dumping database tables:"
ActiveRecord::Base.connection.tables.each do |tbl|
print "- Dumping table #{tbl}... "
@@ -176,9 +170,11 @@ namespace :gitlab do
end
task :db_restore=> :environment do
- backup_path_db = File.join(Gitlab.config.backup_path, "db")
+ backup_path_db = File.join(Gitlab.config.backup_path, "db")
+
puts "Restoring database tables:"
Rake::Task["db:reset"].invoke
+
Dir.glob(File.join(backup_path_db, "*.yml") ).each do |dir|
fixture_file = File.basename(dir, ".*" )
print "- Loading fixture #{fixture_file}..."
diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake
index 0a1a0fa7350..13b4bab6edc 100644
--- a/lib/tasks/gitlab/enable_automerge.rake
+++ b/lib/tasks/gitlab/enable_automerge.rake
@@ -1,7 +1,7 @@
namespace :gitlab do
namespace :app do
desc "GITLAB | Enable auto merge"
- task :enable_automerge => :environment do
+ task :enable_automerge => :environment do
Gitlab::Gitolite.new.enable_automerge
Project.find_each do |project|
diff --git a/lib/tasks/gitlab/gitolite_rebuild.rake b/lib/tasks/gitlab/gitolite_rebuild.rake
index 534aa315631..fce10eb5b69 100644
--- a/lib/tasks/gitlab/gitolite_rebuild.rake
+++ b/lib/tasks/gitlab/gitolite_rebuild.rake
@@ -1,11 +1,10 @@
namespace :gitlab do
namespace :gitolite do
desc "GITLAB | Rebuild each project at gitolite config"
- task :update_repos => :environment do
+ task :update_repos => :environment do
puts "Starting Projects"
Project.find_each(:batch_size => 100) do |project|
- puts
- puts "=== #{project.name}"
+ puts "\n=== #{project.name}"
project.update_repository
puts
end
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index 49c86461c0b..08f35c7e3f0 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -4,8 +4,7 @@ namespace :gitlab do
task :setup => [
'db:setup',
'db:seed_fu',
- 'gitlab:app:enable_automerge'
+ 'gitlab:app:enable_automerge'
]
end
end
-
diff --git a/lib/tasks/gitlab/status.rake b/lib/tasks/gitlab/status.rake
index e5b5e122a18..302f417c01a 100644
--- a/lib/tasks/gitlab/status.rake
+++ b/lib/tasks/gitlab/status.rake
@@ -1,37 +1,37 @@
namespace :gitlab do
namespace :app do
- desc "GITLAB | Check gitlab installation status"
+ desc "GITLAB | Check GitLab installation status"
task :status => :environment do
- puts "Starting diagnostic".yellow
+ puts "Starting diagnostics".yellow
git_base_path = Gitlab.config.git_base_path
print "config/database.yml............"
- if File.exists?(File.join Rails.root, "config", "database.yml")
+ if File.exists?(Rails.root.join "config", "database.yml")
puts "exists".green
- else
+ else
puts "missing".red
return
end
print "config/gitlab.yml............"
- if File.exists?(File.join Rails.root, "config", "gitlab.yml")
- puts "exists".green
+ if File.exists?(Rails.root.join "config", "gitlab.yml")
+ puts "exists".green
else
puts "missing".red
return
end
print "#{git_base_path}............"
- if File.exists?(git_base_path)
- puts "exists".green
- else
+ if File.exists?(git_base_path)
+ puts "exists".green
+ else
puts "missing".red
return
end
print "#{git_base_path} is writable?............"
if File.stat(git_base_path).writable?
- puts "YES".green
+ puts "YES".green
else
puts "NO".red
return
@@ -41,16 +41,16 @@ namespace :gitlab do
`git clone #{Gitlab.config.gitolite_admin_uri} /tmp/gitolite_gitlab_test`
FileUtils.rm_rf("/tmp/gitolite_gitlab_test")
print "Can clone gitolite-admin?............"
- puts "YES".green
- rescue
+ puts "YES".green
+ rescue
print "Can clone gitolite-admin?............"
puts "NO".red
return
end
print "UMASK for .gitolite.rc is 0007? ............"
- unless open("#{git_base_path}/../.gitolite.rc").grep(/UMASK([ \t]*)=([ \t>]*)0007/).empty?
- puts "YES".green
+ if open("#{git_base_path}/../.gitolite.rc").grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?
+ puts "YES".green
else
puts "NO".red
return
@@ -69,16 +69,15 @@ namespace :gitlab do
end
end
-
- if Project.count > 0
+ if Project.count > 0
puts "Validating projects repositories:".yellow
Project.find_each(:batch_size => 100) do |project|
print "#{project.name}....."
- hook_file = File.join(project.path_to_repo, 'hooks','post-receive')
+ hook_file = File.join(project.path_to_repo, 'hooks', 'post-receive')
unless File.exists?(hook_file)
- puts "post-receive file missing".red
- next
+ puts "post-receive file missing".red
+ return
end
puts "post-receive file ok".green
diff --git a/lib/tasks/gitlab/write_hook.rake b/lib/tasks/gitlab/write_hook.rake
index 5e9fc8eb3d1..ccc96aad4f0 100644
--- a/lib/tasks/gitlab/write_hook.rake
+++ b/lib/tasks/gitlab/write_hook.rake
@@ -4,7 +4,6 @@ namespace :gitlab do
task :write_hooks => :environment do
gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")
gitlab_hooks_path = Rails.root.join("lib", "hooks")
-
gitlab_hook_files = ['post-receive']
gitlab_hook_files.each do |file_name|
@@ -20,4 +19,3 @@ namespace :gitlab do
end
end
end
-
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index bb124d8b303..d450b687caf 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe TreeHelper do
describe '#markup?' do
- %w(mdown md markdown textile rdoc org creole mediawiki rst asciidoc pod).each do |type|
+ %w(textile rdoc org creole mediawiki rst asciidoc pod).each do |type|
it "returns true for #{type} files" do
markup?("README.#{type}").should be_true
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 081767543e2..14a373e10a5 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -73,4 +73,30 @@ describe User do
user.authentication_token.should_not be_blank
end
end
+
+ describe "attributes can be changed by a regular user" do
+ before do
+ @user = Factory :user
+ @user.update_attributes(skype: "testskype", linkedin: "testlinkedin")
+ end
+ it { @user.skype.should == 'testskype' }
+ it { @user.linkedin.should == 'testlinkedin' }
+ end
+
+ describe "attributes that shouldn't be changed by a regular user" do
+ before do
+ @user = Factory :user
+ @user.update_attributes(projects_limit: 50)
+ end
+ it { @user.projects_limit.should_not == 50 }
+ end
+
+ describe "attributes can be changed by an admin user" do
+ before do
+ @admin_user = Factory :admin
+ @admin_user.update_attributes({ skype: "testskype", projects_limit: 50 }, as: :admin)
+ end
+ it { @admin_user.skype.should == 'testskype' }
+ it { @admin_user.projects_limit.should == 50 }
+ end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index b46380b21d9..498bbad6179 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -111,42 +111,52 @@ describe Gitlab::API do
end
end
- describe "GET /projects/:id/users" do
- it "should return project users" do
- get api("/projects/#{project.code}/users", user)
-
+ describe "GET /projects/:id/members" do
+ it "should return project team members" do
+ get api("/projects/#{project.code}/members", user)
response.status.should == 200
-
json_response.should be_an Array
json_response.count.should == 2
- json_response.first['user']['id'].should == user.id
+ json_response.first['email'].should == user.email
end
end
- describe "POST /projects/:id/users" do
- it "should add users to project" do
- expect {
- post api("/projects/#{project.code}/users", user),
- user_ids: {"0" => user2.id}, project_access: UsersProject::DEVELOPER
- }.to change {project.users_projects.where(:project_access => UsersProject::DEVELOPER).count}.by(1)
+ describe "GET /projects/:id/members/:user_id" do
+ it "should return project team member" do
+ get api("/projects/#{project.code}/members/#{user.id}", user)
+ response.status.should == 200
+ json_response['email'].should == user.email
+ json_response['access_level'].should == UsersProject::MASTER
end
end
- describe "PUT /projects/:id/users" do
- it "should update users to new access role" do
+ describe "POST /projects/:id/members" do
+ it "should add user to project team" do
expect {
- put api("/projects/#{project.code}/users", user),
- user_ids: {"0" => user3.id}, project_access: UsersProject::MASTER
- }.to change {project.users_projects.where(:project_access => UsersProject::MASTER).count}.by(1)
+ post api("/projects/#{project.code}/members", user), user_id: user2.id,
+ access_level: UsersProject::DEVELOPER
+ }.to change { UsersProject.count }.by(1)
+
+ response.status.should == 201
+ json_response['email'].should == user2.email
+ json_response['access_level'].should == UsersProject::DEVELOPER
+ end
+ end
+
+ describe "PUT /projects/:id/members/:user_id" do
+ it "should update project team member" do
+ put api("/projects/#{project.code}/members/#{user3.id}", user), access_level: UsersProject::MASTER
+ response.status.should == 200
+ json_response['email'].should == user3.email
+ json_response['access_level'].should == UsersProject::MASTER
end
end
- describe "DELETE /projects/:id/users" do
- it "should delete users from project" do
+ describe "DELETE /projects/:id/members/:user_id" do
+ it "should remove user from project team" do
expect {
- delete api("/projects/#{project.code}/users", user),
- user_ids: {"0" => user3.id}
- }.to change {project.users_projects.count}.by(-1)
+ delete api("/projects/#{project.code}/members/#{user3.id}", user)
+ }.to change { UsersProject.count }.by(-1)
end
end
@@ -189,6 +199,27 @@ describe Gitlab::API do
end
end
+ describe "GET /projects/:id/repository/commits" do
+ context "authorized user" do
+ before { project.add_access(user2, :read) }
+
+ it "should return project commits" do
+ get api("/projects/#{project.code}/repository/commits", user)
+ response.status.should == 200
+
+ json_response.should be_an Array
+ json_response.first['id'].should == project.commit.id
+ end
+ end
+
+ context "unauthorized user" do
+ it "should not return project commits" do
+ get api("/projects/#{project.code}/repository/commits")
+ response.status.should == 401
+ end
+ end
+ end
+
describe "GET /projects/:id/snippets/:snippet_id" do
it "should return a project snippet" do
get api("/projects/#{project.code}/snippets/#{snippet.id}", user)
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
new file mode 100644
index 00000000000..f251f3921ac
--- /dev/null
+++ b/spec/requests/api/session_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+ include ApiHelpers
+
+ let(:user) { Factory :user }
+
+ describe "POST /session" do
+ context "when valid password" do
+ it "should return private token" do
+ post api("/session"), email: user.email, password: '123456'
+ response.status.should == 201
+
+ json_response['email'].should == user.email
+ json_response['private_token'].should == user.private_token
+ end
+ end
+
+ context "when invalid password" do
+ it "should return authentication error" do
+ post api("/session"), email: user.email, password: '123'
+ response.status.should == 401
+
+ json_response['email'].should be_nil
+ json_response['private_token'].should be_nil
+ end
+ end
+
+ context "when empty password" do
+ it "should return authentication error" do
+ post api("/session"), email: user.email
+ response.status.should == 401
+
+ json_response['email'].should be_nil
+ json_response['private_token'].should be_nil
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/ssh_keys_spec.rb b/spec/requests/api/ssh_keys_spec.rb
deleted file mode 100644
index 7fb8c920fb1..00000000000
--- a/spec/requests/api/ssh_keys_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Keys do
- include ApiHelpers
- let(:user) {
- user = Factory.create :user
- user.reset_authentication_token!
- user
- }
- let(:key) { Factory.create :key, { user: user}}
-
- describe "GET /keys" do
- context "when unauthenticated" do
- it "should return authentication error" do
- get api("/keys")
- response.status.should == 401
- end
- end
- context "when authenticated" do
- it "should return array of ssh keys" do
- user.keys << key
- user.save
- get api("/keys", user)
- response.status.should == 200
- json_response.should be_an Array
- json_response.first["title"].should == key.title
- end
- end
- end
-
- describe "GET /keys/:id" do
- it "should returm single key" do
- user.keys << key
- user.save
- get api("/keys/#{key.id}", user)
- response.status.should == 200
- json_response["title"].should == key.title
- end
- it "should return 404 Not Found within invalid ID" do
- get api("/keys/42", user)
- response.status.should == 404
- end
- end
-
- describe "POST /keys" do
- it "should not create invalid ssh key" do
- post api("/keys", user), { title: "invalid key" }
- response.status.should == 404
- end
- it "should create ssh key" do
- key_attrs = Factory.attributes :key
- expect {
- post api("/keys", user), key_attrs
- }.to change{ user.keys.count }.by(1)
- end
- end
-
- describe "DELETE /keys/:id" do
- it "should delete existed key" do
- user.keys << key
- user.save
- expect {
- delete api("/keys/#{key.id}", user)
- }.to change{user.keys.count}.by(-1)
- end
- it "should return 404 Not Found within invalid ID" do
- delete api("/keys/42", user)
- response.status.should == 404
- end
- end
-
-end
-
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index e25fe1341d5..243f70f5230 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
describe Gitlab::API do
include ApiHelpers
- let(:user) { Factory :user }
+ let(:user) { Factory :user }
+ let(:key) { Factory :key, user: user }
describe "GET /users" do
context "when unauthenticated" do
@@ -38,4 +39,68 @@ describe Gitlab::API do
json_response['email'].should == user.email
end
end
+
+ describe "GET /user/keys" do
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/user/keys")
+ response.status.should == 401
+ end
+ end
+
+ context "when authenticated" do
+ it "should return array of ssh keys" do
+ user.keys << key
+ user.save
+ get api("/user/keys", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first["title"].should == key.title
+ end
+ end
+ end
+
+ describe "GET /user/keys/:id" do
+ it "should returm single key" do
+ user.keys << key
+ user.save
+ get api("/user/keys/#{key.id}", user)
+ response.status.should == 200
+ json_response["title"].should == key.title
+ end
+
+ it "should return 404 Not Found within invalid ID" do
+ get api("/user/keys/42", user)
+ response.status.should == 404
+ end
+ end
+
+ describe "POST /user/keys" do
+ it "should not create invalid ssh key" do
+ post api("/user/keys", user), { title: "invalid key" }
+ response.status.should == 404
+ end
+
+ it "should create ssh key" do
+ key_attrs = Factory.attributes :key
+ expect {
+ post api("/user/keys", user), key_attrs
+ }.to change{ user.keys.count }.by(1)
+ end
+ end
+
+ describe "DELETE /user/keys/:id" do
+ it "should delete existed key" do
+ user.keys << key
+ user.save
+ expect {
+ delete api("/user/keys/#{key.id}", user)
+ }.to change{user.keys.count}.by(-1)
+ end
+
+ it "should return 404 Not Found within invalid ID" do
+ delete api("/user/keys/42", user)
+ response.status.should == 404
+ end
+ end
end