[#82] Merge branch 'master' into 65-build_repo

Conflicts:
	spec/models/cancan_spec.rb
This commit is contained in:
Pavel Chipiga 2011-12-26 14:51:30 +02:00
commit 7d3dd5eaf1
35 changed files with 802 additions and 15 deletions

View File

@ -0,0 +1,72 @@
class CommentsController < ApplicationController
before_filter :authenticate_user!
before_filter :set_commentable, :only => [:index, :edit, :create]
before_filter :find_project, :only => [:index]
before_filter :find_comment, :only => [:edit, :update, :destroy]
authorize_resource :only => [:show, :edit, :update, :destroy]
authorize_resource :project, :only => [:index]
def index
@comments = @commentable.comments
end
def create
@comment = @commentable.comments.build(params[:comment])
@comment.user = current_user
if @comment.save
flash[:notice] = I18n.t("flash.comment.saved")
redirect_to :back
else
flash[:error] = I18n.t("flash.comment.saved_error")
render :action => 'new'
end
end
def edit
@issue = @commentable
@project = @issue.project
end
def update
if @comment.update_attributes(params[:comment])
flash[:notice] = I18n.t("flash.comment.saved")
#redirect_to :back
redirect_to show_issue_path(@comment.commentable.project, @comment.commentable.serial_id)
else
flash[:error] = I18n.t("flash.comment.saved_error")
render :action => 'new'
end
end
def destroy
@comment.destroy
flash[:notice] = t("flash.comment.destroyed")
redirect_to :back
end
private
def find_commentable
#params.each do |name, value|
# if name =~ /(.+)_id$/
# return $1.classify.constantize.find(value)
# end
#end
#nil
return Issue.find(params[:issue_id])
end
def set_commentable
@commentable = find_commentable
end
def find_comment
@comment = Comment.find(params[:id])
end
def find_project
@project = @comment.commentable.project
end
end

View File

@ -0,0 +1,78 @@
class IssuesController < ApplicationController
before_filter :authenticate_user!
before_filter :find_project, :except => [:destroy]
before_filter :find_and_authorize_by_serial_id, :only => [:show, :edit]
before_filter :set_issue_stub, :only => [:new, :create]
load_and_authorize_resource :except => [:show, :edit, :index]
authorize_resource :project, :only => [:index]
autocomplete :user, :uname
def index
@issues = Issue.scoped
@issues = @project.issues
case params[:status]
when 'open'
@issues = @issues.where(:status => 'open')
when 'closed'
@issues = @issues.where(:status => 'closed')
end
@issues = @issues.paginate :per_page => 10, :page => params[:page]
end
def create
@user_id = params[:user_id]
@user_uname = params[:user_uname]
@issue = Issue.new(params[:issue])
@issue.user_id = @user_id
@issue.project_id = @project.id
if @issue.save!
flash[:notice] = I18n.t("flash.issue.saved")
redirect_to project_issues_path(@project)
else
flash[:error] = I18n.t("flash.issue.saved_error")
render :action => :new
end
end
def edit
@user_id = @issue.user_id
@user_uname = @issue.user.uname
end
def update
@user_id = params[:user_id].blank? ? @issue.user_id : params[:user_id]
@user_uname = params[:user_uname].blank? ? @issue.user.uname : params[:user_uname]
if @issue.update_attributes( params[:issue].merge({:user_id => @user_id}) )
flash[:notice] = I18n.t("flash.issue.saved")
redirect_to show_issue_path(@project, @issue.serial_id)
else
flash[:error] = I18n.t("flash.issue.saved_error")
render :action => :new
end
end
def destroy
@issue.destroy
flash[:notice] = t("flash.issue.destroyed")
redirect_to root_path
end
private
def find_project
@project = Project.find(params[:project_id])
end
def find_and_authorize_by_serial_id
@issue = @project.issues.where(:serial_id => params[:serial_id])[0]
authorize! params[:action].to_sym, @issue
end
def set_issue_stub
@issue = Issue.new(:project => @project)
end
end

View File

@ -0,0 +1,2 @@
module CommentsHelper
end

View File

@ -0,0 +1,2 @@
module IssuesHelper
end

View File

@ -3,7 +3,7 @@ class Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
@ -77,7 +77,7 @@ class Ability
can [:read, :update], Group, groups_in_relations_with(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id) do |group|
group.objects.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id)
end
can :manage, Platform, :owner_type => 'User', :owner_id => user.id
can :manage, Platform, platforms_in_relations_with(:role => 'admin', :object_type => 'User', :object_id => user.id) do |platform|
platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
@ -99,10 +99,40 @@ class Ability
can [:new, :create], Repository do |repository|
repository.platform.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end
can [:read, :index], Issue do |issue|
issue.status == 'open'
end
#can [:read], Issue, :status => 'open'
#can [:show], Issue, with_project_id_in_relations_with(:object_type => 'User', :object_id => user.id)
can [:read, :index], Issue do |issue|
issue.project.relations.exists?(:object_type => 'User', :object_id => user.id)
end
can [:create, :new], Issue do |issue|
issue.project.relations.exists?(:role => ['writer', 'admin'], :object_type => 'User', :object_id => user.id)
end
can [:edit, :update], Issue do |issue|
issue.user_id == user.id || (user.id == issue.project.owner_id && issue.project.owner_type == 'User') ||
issue.project.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end
can [:create, :new], Comment do |comment|
comment.commentable.project.relations.exists?(:object_type => 'User', :object_id => user.id)
end
can [:edit, :update], Comment do |comment|
comment.user_id == user.id || (user.id == comment.commentable.project.owner_id && comment.commentable.project.owner_type == 'User') ||
comment.commentable.project.relations.exists?(:role => 'admin', :object_type => 'User', :object_id => user.id)
end
#
cannot [:index, :edit, :update, :create, :new, :read, :show], Issue do |issue|
!issue.project.has_issues
end
cannot [:edit, :update, :create, :new, :destroy], Comment do |comment|
!comment.commentable.project.has_issues
end
#can :read, Repository
# TODO: Add personal repos rules
# Same rights for groups:
can [:read, :create], PrivateUser, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
can :publish, BuildList do |build_list|
@ -125,7 +155,7 @@ class Ability
can [:read, :update], Project, projects_in_relations_with(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids) do |project|
project.relations.exists?(:role => ['writer', 'admin'], :object_type => 'Group', :object_id => user.group_ids)
end
can :manage, Platform, :owner_type => 'Group', :owner_id => user.group_ids
#can :read, Platform, :groups => {:id => user.group_ids}
can :read, Platform, platforms_in_relations_with(:role => 'reader', :object_type => 'Group', :object_id => user.group_ids) do |platform|
@ -145,11 +175,12 @@ class Ability
cannot :create, [Platform, User]
end
end
# Shared cannot rights for all users (guests, registered, admin)
cannot :destroy, Platform, :platform_type => 'personal'
cannot :destroy, Repository, :platform => {:platform_type => 'personal'}
cannot :fork, Project, :owner_id => user.id, :owner_type => user.class.to_s
cannot :destroy, Issue
end
# Sub query for platforms, projects relations
@ -166,6 +197,16 @@ class Ability
end
end
def with_project_id_in_relations_with(opts = {})
query = "issues.project_id IN (SELECT target_id FROM relations WHERE relations.target_type = 'issues'"
opts.each do |key, value|
query = query + " AND relations.#{ key } #{ value.class == Array ? 'IN (?)' : '= ?' } "
end
query = query + ")"
return opts.values.unshift query
end
def build_lists_in_relations_with(opts)
query = "build_lists.project_id IN (SELECT target_id FROM relations WHERE relations.target_type = 'Project'"
opts.each do |key, value|

6
app/models/comment.rb Normal file
View File

@ -0,0 +1,6 @@
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
belongs_to :user
validates :body, :user_id, :commentable_id, :commentable_type, :presence => true
end

21
app/models/issue.rb Normal file
View File

@ -0,0 +1,21 @@
class Issue < ActiveRecord::Base
STATUSES = ['open', 'closed']
belongs_to :project
belongs_to :user
has_many :comments, :as => :commentable
validates :title, :body, :project_id, :user_id, :presence => true
#attr_readonly :serial_id
after_create :set_serial_id
protected
def set_serial_id
self.serial_id = self.project.issues.count
self.save!
end
end

View File

@ -4,6 +4,7 @@ class Project < ActiveRecord::Base
belongs_to :category, :counter_cache => true
belongs_to :owner, :polymorphic => true
has_many :issues, :dependent => :destroy
has_many :build_lists, :dependent => :destroy
has_many :auto_build_lists, :dependent => :destroy

View File

@ -7,4 +7,14 @@ class ProjectToRepository < ActiveRecord::Base
after_create lambda { project.xml_rpc_create(repository) }, :unless => lambda {Thread.current[:skip]}
after_destroy lambda { project.xml_rpc_destroy(repository) }
# after_rollback lambda { project.xml_rpc_destroy(repository) rescue true if new_record? }
validate :one_project_in_platform_repositories
protected
def one_project_in_platform_repositories
c = Platform.scoped.select('projects.*').joins(:repositories => :projects).where(
:projects => {:name => project.name}, :id => repository.platform_id).count
errors.add(:project, 'should be one in platform') if c > 0
end
end

View File

@ -0,0 +1,10 @@
.group
= f.label :body, :class => :label
= f.text_area :body, :class => 'text_field', :cols => 80
.group.navform.wat-cf
%button.button{:type => "submit"}
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
= t("layout.save")
%span.text_button_padding= t("layout.or")
= link_to t("layout.cancel"), show_issue_path(@issue.project, @issue.serial_id), :class => "text_button_padding link_button"

View File

@ -0,0 +1,10 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to t("layout.issues.list"), project_issue_path(@project, @issue)
.content
%h2.title
= t("layout.issues.edit_header")
.inner
= form_for @comment, :url => project_issue_comment_path(@project, @issue, @comment), :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f}

View File

@ -0,0 +1,25 @@
= javascript_include_tag "autocomplete-rails.js"
.group
= f.label :title, :class => :label
= f.text_field :title, :class => 'text_field'
.group
= f.label :body, :class => :label
= f.text_area :body, :class => 'text_field', :cols => 80
.group
= f.label :status, :class => :label
= f.select :status, Issue::STATUSES, :class => 'text_field'
.group
= label_tag "", t("layout.issues.user_id"), :class => :label
= autocomplete_field_tag 'user_id', @user_uname, autocomplete_user_uname_platforms_path, :id_element => '#user_id_field'
= hidden_field_tag 'user_id', @user_id, :id => 'user_id_field'
.group.navform.wat-cf
%button.button{:type => "submit"}
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
= t("layout.save")
%span.text_button_padding= t("layout.or")
= link_to t("layout.cancel"), project_path(@project), :class => "text_button_padding link_button"

View File

@ -0,0 +1,15 @@
%table.table
%tr
%th.first= t("activerecord.attributes.issue.title")
%th.first= t("activerecord.attributes.issue.status")
%th.last &nbsp;
- @issues.each do |issue|
%tr{:class => cycle("odd", "even")}
%td
= link_to issue.title, show_issue_path(@project, issue.serial_id)
%td
= issue.status
%td.last
= link_to t("layout.show"), show_issue_path(@project, issue.serial_id)
|
= link_to t("layout.delete"), project_issue_path(@project, issue), :method => :delete, :confirm => t("layout.issues.confirm_delete") if can? :destroy, issue

View File

@ -0,0 +1,11 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.new"), new_project_issue_path(@project)
.content
%h2.title
= t("layout.issues.edit_header")
.inner
= form_for @issue, :url => project_issue_path(@project, @issue), :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f}

View File

@ -0,0 +1,22 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first.active= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.new"), new_project_issue_path(@project) if can? :new, Issue.new(:project_id => @project.id)
.secondary-navigation
%ul.wat-cf
%li{:class => "first " + (params[:status].blank? ? "active" : "")}
= link_to t("layout.issues.statuses.any"), project_issues_path(@project)
%li{:class => "first " + (params[:status] == 'open' ? "active" : "")}
= link_to t("layout.issues.statuses.open"), project_issues_path(@project, :status => 'open')
%li{:class => "first " + (params[:status] == 'closed' ? "active" : "")}
= link_to t("layout.issues.statuses.closed"), project_issues_path(@project, :status => 'closed')
.content
%h2.title
= t("layout.issues.list_header")
.inner
= render :partial => 'shared/search_form'
= render :partial => 'issues/list'
.actions-bar.wat-cf
.actions
= will_paginate @issues, :param_name => :issue_page

View File

@ -0,0 +1,11 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to "#{t("layout.issues.list")}", project_issues_path(@project)
%li.active= link_to "#{t("layout.issues.new")}", new_project_issue_path(@project)
.content
%h2.title
= t("layout.issues.new_header")
.inner
= form_for :issue, :url => project_issues_path(@project), :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f}

View File

@ -0,0 +1,53 @@
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to t("layout.issues.list"), project_issues_path(@project)
%li= link_to t("layout.issues.edit"), edit_project_issue_path(@project, @issue.serial_id) if can? :edit, @issue
.content
.inner
%p
%b
= t("activerecord.attributes.issue.title")
\:
= @issue.title
%p
%b
= t("activerecord.attributes.issue.body")
\:
= @issue.body
%p
%b
= t('activerecord.attributes.issue.status')
\:
= @issue.status
%a{ :name => "comments" }
.block
.secondary-navigation
%ul.wat-cf
.content
%h2.title
= t("layout.issues.comments_header")
.inner
%table.table
%tr
%th.first= t("activerecord.attributes.user.uname")
%th.first= t("activerecord.attributes.comment.body")
%th.last &nbsp;
- @issue.comments.each do |comment|
%tr{:class => cycle("odd", "even")}
%td
= comment.user.uname
%td
= comment.body
%td.last
= link_to t("layout.edit"), edit_project_issue_comment_path(@project, @issue, comment) if can? :update, comment
= link_to image_tag("web-app-theme/icons/cross.png", :alt => t("layout.delete")) + " " + t("layout.delete"), project_issue_comment_path(@project, @issue, comment), :method => "delete", :class => "button", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
.block
.content
%h2.title
= t("layout.comments.new_header")
.inner
= form_for :comment, :url => project_issue_comments_path(@project, @issue), :method => :post, :html => { :class => :form } do |f|
= render :partial => "comments/form", :locals => {:f => f}

View File

@ -10,6 +10,9 @@
.group
= f.label :description, t("activerecord.attributes.project.description"), :class => :label
= f.text_area :description, :class => 'text_field', :cols => 80
.group
= f.label :has_issues, t("activerecord.attributes.project.has_issues"), :class => :label
= f.check_box :has_issues
.group.navform.wat-cf
%button.button{:type => "submit"}

View File

@ -6,6 +6,7 @@
%li.active= link_to t("layout.projects.show"), project_path(@project)
%li= link_to t("layout.git.repositories.source"), project_repo_path(@project)
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
%li= link_to t("layout.projects.issues"), project_issues_path(@project)
.content
.inner

View File

@ -83,6 +83,7 @@ ru:
confirm_regenerate: Вы уверены, что хотите перегенерировать эту пару логин/пароль?
regenerate_btn: Перегенерировать
warning_message: Примечание - При получении новых данных старые становятся недействительными
categories:
list: Список
new: Создать
@ -93,6 +94,23 @@ ru:
edit_header: Редактировать категорию
confirm_delete: Вы уверены, что хотите удалить эту категорию?
issues:
list: Список
edit: Редактировать
comments_header: Комментарии
new: Новая задача
list_header: Список
confirm_delete: Вы уверены, что хотите удалить эту задачу?
new_header: Новая задача
statuses:
open: Открытые
closed: Закрытые
any: Все
comments:
confirm_delete: Вы уверены, что хотите удалить комментарий?
new_header: Новый комментарий
platforms:
admin_id: Владелец
build_all: Собрать все
@ -214,6 +232,7 @@ ru:
collaborators: Коллабораторы
groups: Группы
edit_collaborators: Изменить список участников
issues: Задачи
collaborators:
back_to_proj: Вернуться к проекту
@ -334,7 +353,7 @@ ru:
downloads:
statistics_refreshed: Статистика обновлена
collaborators:
successfully_changed: Список коллабораторов успешно изменен
error_in_changing: Ошибка изменения списка коллабораторов
@ -355,12 +374,19 @@ ru:
failed: Не удалось автоматизировать сборку!
cancel: Автоматическая сборка проекта отменена!
cancel_failed: Не удалось отменить автоматическую сборку проекта!
category:
saved: Категория успешно сохранена
save_error: Не удалось сохранить категорию
destroyed: Категория успешно удалена
comment:
saved: Комментарий успешно сохранен
destroyed: Комментарий удален
issue:
saved: Задача успешно сохранена
project:
saved: Проект успешно сохранен
save_error: Не удалось сохранить проект
@ -456,7 +482,18 @@ ru:
pl: Платформа
arch_id: Архитектура
arch: Архитектура
comment:
body: Содержание
user: Автор
issue:
title: Заголовок
body: Содержание
user: Назначено
project: Проект
status: Статус
private_user:
login: Логин
password: Пароль
@ -537,6 +574,7 @@ ru:
repository: Репозиторий
created_at: Создан
updated_at: Обновлен
has_issues: Включить трэкер
rpm:
name: Название

View File

@ -78,7 +78,12 @@ Rosa::Application.routes.draw do
resources :categories, :only => [:index, :show]
end
match "projects/:project_id/issues/:serial_id" => 'issues#show', :serial_id => /\d+/, :as => :show_issue, :via => :get
match "projects/:project_id/issues/:serial_id/edit" => 'issues#edit', :serial_id => /\d+/, :as => :edit_issue, :via => :get
resources :projects do
resources :issues, :except => [:show] do
resources :comments, :only => [:edit, :create, :update, :destroy]
end
resource :repo, :controller => "git/repositories", :only => [:show]
resources :build_lists, :only => [:index, :new, :create]

View File

@ -0,0 +1,20 @@
class CreateIssues < ActiveRecord::Migration
def self.up
create_table :issues do |t|
t.integer :serial_id
t.integer :project_id
t.integer :user_id
t.string :title
t.text :body
t.string :status
t.timestamps
end
add_index :issues, [:project_id, :serial_id], :unique => true
end
def self.down
drop_table :issues
end
end

View File

@ -0,0 +1,16 @@
class CreateComments < ActiveRecord::Migration
def self.up
create_table :comments do |t|
t.integer :commentable_id
t.string :commentable_type
t.integer :user_id
t.text :body
t.timestamps
end
end
def self.down
drop_table :comments
end
end

View File

@ -0,0 +1,9 @@
class AddHasIssuesToProjects < ActiveRecord::Migration
def self.up
add_column :projects, :has_issues, :boolean, :default => true
end
def self.down
remove_column :projects, :has_issues
end
end

View File

@ -85,6 +85,15 @@ ActiveRecord::Schema.define(:version => 20111221194422) do
t.datetime "updated_at"
end
create_table "comments", :force => true do |t|
t.integer "commentable_id"
t.string "commentable_type"
t.integer "user_id"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "containers", :force => true do |t|
t.string "name", :null => false
t.integer "project_id", :null => false
@ -142,6 +151,19 @@ ActiveRecord::Schema.define(:version => 20111221194422) do
t.string "uname"
end
create_table "issues", :force => true do |t|
t.integer "serial_id"
t.integer "project_id"
t.integer "user_id"
t.string "title"
t.text "body"
t.string "status"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true
create_table "platforms", :force => true do |t|
t.string "description"
t.string "name"
@ -213,6 +235,7 @@ ActiveRecord::Schema.define(:version => 20111221194422) do
t.integer "category_id"
t.text "description"
t.string "ancestry"
t.boolean "has_issues", :default => true
end
add_index "projects", ["category_id"], :name => "index_projects_on_category_id"

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe CommentsController do
end

View File

@ -0,0 +1,194 @@
require 'spec_helper'
shared_examples_for 'issue user with project reader rights' do
#it_should_behave_like 'user with rights to view issues'
it 'should be able to perform index action' do
get :index, :project_id => @project.id
response.should render_template(:index)
end
it 'should be able to perform show action' do
get :show, :project_id => @project.id, :serial_id => @issue.serial_id
response.should render_template(:show)
end
end
shared_examples_for 'issue user with project writer rights' do
it 'should be able to perform create action' do
post :create, @create_params
response.should redirect_to(project_issues_path(@project))
end
it 'should create issue object into db' do
lambda{ post :create, @create_params }.should change{ Issue.count }.by(1)
end
end
shared_examples_for 'user with issue update rights' do
it 'should be able to perform update action' do
put :update, {:id => @issue.id}.merge(@update_params)
response.should redirect_to(show_issue_path(@project, @issue.serial_id))
end
it 'should update issue title' do
put :update, {:id => @issue.id}.merge(@update_params)
@issue.reload.title.should == 'issue2'
end
end
shared_examples_for 'user without issue update rights' do
it 'should not be able to perform update action' do
put :update, {:id => @issue.id}.merge(@update_params)
response.should redirect_to(forbidden_path)
end
it 'should not update issue title' do
put :update, {:id => @issue.id}.merge(@update_params)
@issue.reload.title.should_not == 'issue2'
end
end
shared_examples_for 'user without issue destroy rights' do
it 'should not be able to perform destroy action' do
delete :destroy, :id => @issue.id, :project_id => @project.id
response.should redirect_to(forbidden_path)
end
it 'should not reduce issues count' do
lambda{ delete :destroy, :id => @issue.id, :project_id => @project.id }.should change{ Issue.count }.by(0)
end
end
shared_examples_for 'project with issues turned off' do
pending 'should not be able to perform index action' do
get :index, :project_id => @project_with_turned_off_issues.id
#response.should redirect_to(forbidden_path)
response.should render_template(:index)
end
it 'should not be able to perform show action' do
get :show, :project_id => @project_with_turned_off_issues.id, :serial_id => @turned_of_issue.serial_id
response.should redirect_to(forbidden_path)
end
end
describe IssuesController do
before(:each) do
stub_rsync_methods
@project = Factory(:project)
@issue_user = Factory(:user)
@create_params = {:project => {:name => 'pro'}}
@update_params = {:project => {:name => 'pro2'}}
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
@issue = Factory(:issue, :project_id => @project.id, :user_id => @issue_user.id)
@create_params = {
:project_id => @project.id,
:issue => {
:title => "issue1",
:body => "issue body",
:project_id => @project.id
},
:user_id => @issue_user.id,
:user_uname => @issue_user.uname
}
@update_params = {
:project_id => @project.id,
:issue => {
:title => "issue2"
}
}
@project_with_turned_off_issues = Factory(:project, :has_issues => false)
@turned_of_issue = Factory(:issue, :project_id => @project_with_turned_off_issues.id, :user_id => @issue_user.id)
end
context 'for global admin user' do
before(:each) do
@admin = Factory(:admin)
set_session_for(@admin)
end
it_should_behave_like 'user without issue destroy rights'
end
context 'for project admin user' do
before(:each) do
#@admin = Factory(:admin)
#set_session_for(@admin)
@user = Factory(:user)
set_session_for(@user)
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
end
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user with issue update rights'
it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
end
context 'for project owner user' do
before(:each) do
@user = Factory(:user)
set_session_for(@user)
@project.update_attribute(:owner, @user)
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
end
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user with issue update rights'
it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
end
context 'for project reader user' do
before(:each) do
@user = Factory(:user)
set_session_for(@user)
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'reader')
end
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'user without issue update rights'
it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
it 'should not be able to perform create action' do
post :create, @create_params
response.should redirect_to(forbidden_path)
end
it 'should not create issue object into db' do
lambda{ post :create, @create_params }.should change{ Issue.count }.by(0)
end
end
context 'for project writer user' do
before(:each) do
@user = Factory(:user)
set_session_for(@user)
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'writer')
end
it_should_behave_like 'issue user with project reader rights'
it_should_behave_like 'issue user with project writer rights'
it_should_behave_like 'user without issue update rights'
it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
end
context 'for issue assign user' do
before(:each) do
set_session_for(@issue_user)
#@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'writer')
end
it_should_behave_like 'user with issue update rights'
it_should_behave_like 'user without issue destroy rights'
it_should_behave_like 'project with issues turned off'
end
end

View File

@ -0,0 +1,6 @@
# Read about factories at http://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :comment do
end
end

6
spec/factories/issues.rb Normal file
View File

@ -0,0 +1,6 @@
Factory.define(:issue) do |p|
p.title { Factory.next(:string) }
p.body { Factory.next(:string) }
p.association :user, :factory => :user
p.status "open"
end

View File

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the CommentsHelper. For example:
#
# describe CommentsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe CommentsHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the IssuesHelper. For example:
#
# describe IssuesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe IssuesHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -118,6 +118,7 @@ describe CanCan do
context 'as project collaborator' do
before(:each) do
@project = Factory(:project)
@issue = Factory(:issue, :project_id => @project.id)
end
context 'with read rights' do
@ -128,18 +129,22 @@ describe CanCan do
it 'should be able to read project' do
@ability.should be_able_to(:read, @project)
end
it 'should be able to read project' do
it 'should be able to read open platform' do
@ability.should be_able_to(:read, open_platform)
end
it 'should be able to read issue' do
@ability.should be_able_to(:read, @issue)
end
end
context 'with write rights' do
context 'with writer rights' do
before(:each) do
@project.relations.create!(:object_id => @user.id, :object_type => 'User', :role => 'writer')
end
[:read, :update].each do |action|
[:read, :create, :new].each do |action|
it "should be able to #{ action } project" do
@ability.should be_able_to(action, @project)
end
@ -174,11 +179,18 @@ describe CanCan do
it "should be able to manage collaborators of project" do
@ability.should be_able_to(:manage_collaborators, @project)
end
[:read, :create, :new, :update, :edit].each do |action|
it "should be able to #{ action } issue" do
@ability.should be_able_to(action, @issue)
end
end
end
context 'with owner rights' do
before(:each) do
@project.update_attribute(:owner, @user)
@issue.project.reload
end
[:read, :update, :destroy].each do |action|
@ -193,6 +205,12 @@ describe CanCan do
@ability.should be_able_to(action, @build_list)
end
end
[:read, :update, :edit].each do |action|
it "should be able to #{ action } issue" do
@ability.should be_able_to(action, @issue)
end
end
end
end

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe Comment do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe Issue do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,5 +1,18 @@
require 'spec_helper'
describe ProjectToRepository do
pending "add some examples to (or delete) #{__FILE__}"
before(:each) do
stub_rsync_methods
@platform = Factory(:platform)
@first_repo = Factory(:repository, :platform_id => @platform.id)
@second_repo = Factory(:repository, :platform_id => @platform.id)
@project = Factory(:project)
@first_repo.projects << @project
@first_repo.save
end
it 'should not add the same project in different repositories of same platform' do
p2r = @second_repo.project_to_repositories.build :project_id => @project.id
p2r.should_not be_valid
end
end