Merge branch 'master' into fix_project_access_notification
This commit is contained in:
commit
c09d233611
|
@ -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
|
||||
|
|
1
Gemfile
1
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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//= require jquery.endless-scroll
|
||||
//= require jquery.highlight
|
||||
//= require jquery.waitforimages
|
||||
//= require jquery.atwho
|
||||
//= require bootstrap
|
||||
//= require modernizr
|
||||
//= require chosen-jquery
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
118
app/assets/stylesheets/sections/events.scss
Normal file
118
app/assets/stylesheets/sections/events.scss
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class HooksController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :project
|
||||
layout "project"
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class LabelsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :project
|
||||
before_filter :module_enabled
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -32,7 +32,11 @@ module TreeHelper
|
|||
#
|
||||
# Returns boolean
|
||||
def markup?(filename)
|
||||
filename.end_with?(*%w(.mdown .md .markdown .textile .rdoc .org .creole
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
& press compare button for commits list, code diff.
|
||||
%code.label_branch master
|
||||
and press compare button for commits list, code diff.
|
||||
|
||||
%br
|
||||
|
||||
|
@ -19,11 +19,13 @@
|
|||
= 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
|
||||
|
@ -34,7 +36,7 @@
|
|||
|
||||
: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');
|
||||
});
|
||||
|
||||
|
|
|
@ -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
|
||||
–
|
||||
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
|
||||
= gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding"
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
- if event.allowed?
|
||||
%div.event-item
|
||||
- if event.issue?
|
||||
.event_feed
|
||||
= render "events/event_issue", event: event
|
||||
|
||||
- elsif event.merge_request?
|
||||
.event_feed
|
||||
= render "events/event_merge_request", event: event
|
||||
|
||||
- elsif event.push?
|
||||
.event_feed
|
||||
= render "events/event_push", event: event
|
||||
|
||||
- elsif event.membership_changed?
|
||||
.event_feed
|
||||
= render "events/event_membership_changed", event: event
|
||||
|
||||
%span.cgray.right
|
||||
= time_ago_in_words(event.created_at)
|
||||
ago.
|
||||
.clearfix
|
||||
|
|
|
@ -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
|
||||
.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
|
||||
%span.cgray
|
||||
= time_ago_in_words(event.created_at)
|
||||
ago.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
= image_tag gravatar_icon(event.author_email), class: "avatar"
|
||||
%strong #{event.author_name}
|
||||
%span.event_label{class: event.action_name}= event.action_name
|
||||
project
|
||||
.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)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
- 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
|
||||
.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
|
||||
%span.cgray
|
||||
= time_ago_in_words(event.created_at)
|
||||
ago.
|
||||
%br
|
||||
.event-body
|
||||
.event-info
|
||||
%span= event.merge_request.source_branch
|
||||
→
|
||||
%span= event.merge_request.target_branch
|
||||
|
|
|
@ -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
|
||||
|
||||
.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
|
||||
%span.cgray
|
||||
= time_ago_in_words(event.created_at)
|
||||
ago.
|
||||
|
||||
- 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
|
||||
.event-body
|
||||
%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|
|
||||
- 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 → #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]}
|
||||
.clearfix
|
||||
|
|
|
@ -1,24 +1,30 @@
|
|||
%h3 API
|
||||
%h3.page_title API
|
||||
.back_link
|
||||
= link_to help_path do
|
||||
← 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
|
||||
= link_to "Issues", "#issues", 'data-toggle' => 'tab'
|
||||
%li
|
||||
= link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
|
||||
|
||||
.file_holder#README
|
||||
.tab-content
|
||||
.tab-pane.active#README
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
README
|
||||
|
@ -26,9 +32,8 @@
|
|||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "README.md"))
|
||||
|
||||
%br
|
||||
|
||||
.file_holder#projects
|
||||
.tab-pane#projects
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
Projects
|
||||
|
@ -36,9 +41,8 @@
|
|||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "projects.md"))
|
||||
|
||||
%br
|
||||
|
||||
.file_holder#snippets
|
||||
.tab-pane#snippets
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
Projects Snippets
|
||||
|
@ -46,9 +50,17 @@
|
|||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
|
||||
|
||||
%br
|
||||
.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"))
|
||||
|
||||
.file_holder#users
|
||||
.tab-pane#users
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
Users
|
||||
|
@ -56,9 +68,17 @@
|
|||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "users.md"))
|
||||
|
||||
%br
|
||||
.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"))
|
||||
|
||||
.file_holder#issues
|
||||
.tab-pane#issues
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
Issues
|
||||
|
@ -66,9 +86,8 @@
|
|||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "issues.md"))
|
||||
|
||||
%br
|
||||
|
||||
.file_holder#milestones
|
||||
.tab-pane#milestones
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
Milestones
|
||||
|
|
|
@ -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>"
|
||||
});
|
||||
});
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
%i.icon-file
|
||||
= content.name
|
||||
.file_content.wiki
|
||||
- if gitlab_markdown?(content.name)
|
||||
= preserve do
|
||||
= markdown(content.data)
|
||||
- else
|
||||
= raw GitHub::Markup.render(content.name, content.data)
|
||||
|
||||
:javascript
|
||||
|
|
|
@ -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
|
||||
|
|
31
config/initializers/4_resque.rb
Normal file
31
config/initializers/4_resque.rb
Normal file
|
@ -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 = []
|
|
@ -1 +0,0 @@
|
|||
Resque.watch_queue(PostReceive.instance_variable_get("@queue"))
|
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
Resque::Mailer.excluded_environments = []
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
Add users to exiting project
|
||||
Get a project team member.
|
||||
|
||||
```
|
||||
POST /projects/:id/users
|
||||
GET /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 user
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
"id": 1,
|
||||
"email": "john@example.com",
|
||||
"name": "John Smith",
|
||||
"blocked": false,
|
||||
"created_at": "2012-05-23T08:00:58Z",
|
||||
"access_level": 40
|
||||
}
|
||||
```
|
||||
|
||||
## 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_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.
|
||||
|
||||
|
|
166
doc/api/repositories.md
Normal file
166
doc/api/repositories.md
Normal file
|
@ -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.
|
22
doc/api/session.md
Normal file
22
doc/api/session.md
Normal file
|
@ -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
|
||||
}
|
||||
```
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -17,6 +17,6 @@ module Gitlab
|
|||
mount Projects
|
||||
mount Issues
|
||||
mount Milestones
|
||||
mount Keys
|
||||
mount Session
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
authorize! :admin_project, user_project
|
||||
user_project.add_users_ids_to_team(params[:user_ids].values, params[:project_access])
|
||||
nil
|
||||
# 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
|
||||
|
||||
# Update users to specified access level
|
||||
# Add a new 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 user
|
||||
# access_level (required) - Project access level
|
||||
# Example Request:
|
||||
# PUT /projects/:id/add_users
|
||||
put ":id/users" do
|
||||
# POST /projects/:id/members
|
||||
post ":id/members" 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.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
|
||||
|
||||
# Delete project users
|
||||
# Update project team member
|
||||
#
|
||||
# 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
|
||||
# access_level (required) - Project access level
|
||||
# Example Request:
|
||||
# DELETE /projects/:id/users
|
||||
delete ":id/users" do
|
||||
# PUT /projects/:id/members/:user_id
|
||||
put ":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]
|
||||
|
||||
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
|
||||
|
||||
# Remove a team member from project
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID or code name of a project
|
||||
# user_id (required) - The ID of a team member
|
||||
# Example Request:
|
||||
# DELETE /projects/:id/members/:user_id
|
||||
delete ":id/members/:user_id" do
|
||||
authorize! :admin_project, user_project
|
||||
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
|
||||
|
|
20
lib/api/session.rb
Normal file
20
lib/api/session.rb
Normal file
|
@ -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
|
|
@ -25,12 +25,59 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
resource :user do
|
||||
# Get currently authenticated user
|
||||
#
|
||||
# Example Request:
|
||||
# GET /user
|
||||
get "/user" do
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
end
|
||||
|
|
|
@ -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 " ERROR: Failed to clone #{existing_path} to #{new_path}"
|
||||
puts " Make sure #{git_user} can reach #{existing_path}"
|
||||
puts " Exception-MSG: #{msg}"
|
||||
false
|
||||
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}"
|
||||
description: "Automatically created from 'import_projects' rake task on #{Time.now}"
|
||||
)
|
||||
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
|
||||
)
|
||||
|
||||
# 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
|
||||
|
|
|
@ -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 ################################
|
||||
|
||||
|
@ -140,7 +133,7 @@ namespace :gitlab do
|
|||
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}",
|
||||
|
@ -158,7 +151,8 @@ namespace :gitlab do
|
|||
|
||||
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)
|
||||
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}... "
|
||||
|
@ -177,8 +171,10 @@ namespace :gitlab do
|
|||
|
||||
task :db_restore=> :environment do
|
||||
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}..."
|
||||
|
|
|
@ -4,8 +4,7 @@ namespace :gitlab 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
|
||||
|
|
|
@ -8,4 +8,3 @@ namespace :gitlab do
|
|||
]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
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
|
||||
puts "missing".red
|
||||
|
@ -14,7 +14,7 @@ namespace :gitlab do
|
|||
end
|
||||
|
||||
print "config/gitlab.yml............"
|
||||
if File.exists?(File.join Rails.root, "config", "gitlab.yml")
|
||||
if File.exists?(Rails.root.join "config", "gitlab.yml")
|
||||
puts "exists".green
|
||||
else
|
||||
puts "missing".red
|
||||
|
@ -49,7 +49,7 @@ namespace :gitlab do
|
|||
end
|
||||
|
||||
print "UMASK for .gitolite.rc is 0007? ............"
|
||||
unless open("#{git_base_path}/../.gitolite.rc").grep(/UMASK([ \t]*)=([ \t>]*)0007/).empty?
|
||||
if open("#{git_base_path}/../.gitolite.rc").grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?
|
||||
puts "YES".green
|
||||
else
|
||||
puts "NO".red
|
||||
|
@ -69,7 +69,6 @@ namespace :gitlab do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
if Project.count > 0
|
||||
puts "Validating projects repositories:".yellow
|
||||
Project.find_each(:batch_size => 100) do |project|
|
||||
|
@ -78,7 +77,7 @@ namespace :gitlab do
|
|||
|
||||
unless File.exists?(hook_file)
|
||||
puts "post-receive file missing".red
|
||||
next
|
||||
return
|
||||
end
|
||||
|
||||
puts "post-receive file ok".green
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "DELETE /projects/:id/users" do
|
||||
it "should delete users from project" do
|
||||
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/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)
|
||||
|
|
39
spec/requests/api/session_spec.rb
Normal file
39
spec/requests/api/session_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
@ -4,6 +4,7 @@ describe Gitlab::API do
|
|||
include ApiHelpers
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue