diff --git a/LICENSE.txt b/LICENSE.txt index 908fc5f26..dcbd52435 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2,8 +2,6 @@ ROSA ABF is Copyright 2010-2013 ROSA CJSC. ROSA CJSC ("ROSA") distributes the ABF source code under the GNU General Public License (GPL), version 2.0 or later. -The image and icon files in ABF are copyright ROSA CJSC ("ROSA"), but unlike the source code they are not licensed under the GPL version 2.0 or later. ROSA grants you the right to use them for testing and development purposes only, but not to use them in production (commercially or non-commercially). - Third-party copyright in this distribution is noted where applicable. All rights not expressly granted are reserved. \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index fe7013d52..000000000 --- a/README +++ /dev/null @@ -1,256 +0,0 @@ -== Welcome to Rails - -Rails is a web-application framework that includes everything needed to create -database-backed web applications according to the Model-View-Control pattern. - -This pattern splits the view (also called the presentation) into "dumb" -templates that are primarily responsible for inserting pre-built data in between -HTML tags. The model contains the "smart" domain objects (such as Account, -Product, Person, Post) that holds all the business logic and knows how to -persist themselves to a database. The controller handles the incoming requests -(such as Save New Account, Update Product, Show Post) by manipulating the model -and directing data to the view. - -In Rails, the model is handled by what's called an object-relational mapping -layer entitled Active Record. This layer allows you to present the data from -database rows as objects and embellish these data objects with business logic -methods. You can read more about Active Record in -link:files/vendor/rails/activerecord/README.html. - -The controller and view are handled by the Action Pack, which handles both -layers by its two parts: Action View and Action Controller. These two layers -are bundled in a single package due to their heavy interdependence. This is -unlike the relationship between the Active Record and Action Pack that is much -more separate. Each of these packages can be used independently outside of -Rails. You can read more about Action Pack in -link:files/vendor/rails/actionpack/README.html. - - -== Getting Started - -1. At the command prompt, create a new Rails application: - rails new myapp (where myapp is the application name) - -2. Change directory to myapp and start the web server: - cd myapp; rails server (run with --help for options) - -3. Go to http://localhost:3000/ and you'll see: - "Welcome aboard: You're riding Ruby on Rails!" - -4. Follow the guidelines to start developing your application. You can find -the following resources handy: - -* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html -* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ - - -== Debugging Rails - -Sometimes your application goes wrong. Fortunately there are a lot of tools that -will help you debug it and get it back on the rails. - -First area to check is the application log files. Have "tail -f" commands -running on the server.log and development.log. Rails will automatically display -debugging and runtime information to these files. Debugging info will also be -shown in the browser on requests from 127.0.0.1. - -You can also log your own messages directly into the log file from your code -using the Ruby logger class from inside your controllers. Example: - - class WeblogController < ActionController::Base - def destroy - @weblog = Weblog.find(params[:id]) - @weblog.destroy - logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") - end - end - -The result will be a message in your log file along the lines of: - - Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! - -More information on how to use the logger is at http://www.ruby-doc.org/core/ - -Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are -several books available online as well: - -* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) -* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) - -These two books will bring you up to speed on the Ruby language and also on -programming in general. - - -== Debugger - -Debugger support is available through the debugger command when you start your -Mongrel or WEBrick server with --debugger. This means that you can break out of -execution at any point in the code, investigate and change the model, and then, -resume execution! You need to install ruby-debug to run the server in debugging -mode. With gems, use sudo gem install ruby-debug. Example: - - class WeblogController < ActionController::Base - def index - @posts = Post.find(:all) - debugger - end - end - -So the controller will accept the action, run the first line, then present you -with a IRB prompt in the server window. Here you can do things like: - - >> @posts.inspect - => "[#nil, "body"=>nil, "id"=>"1"}>, - #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" - >> @posts.first.title = "hello from a debugger" - => "hello from a debugger" - -...and even better, you can examine how your runtime objects actually work: - - >> f = @posts.first - => #nil, "body"=>nil, "id"=>"1"}> - >> f. - Display all 152 possibilities? (y or n) - -Finally, when you're ready to resume execution, you can enter "cont". - - -== Console - -The console is a Ruby shell, which allows you to interact with your -application's domain model. Here you'll have all parts of the application -configured, just like it is when the application is running. You can inspect -domain models, change values, and save to the database. Starting the script -without arguments will launch it in the development environment. - -To start the console, run rails console from the application -directory. - -Options: - -* Passing the -s, --sandbox argument will rollback any modifications - made to the database. -* Passing an environment name as an argument will load the corresponding - environment. Example: rails console production. - -To reload your controllers and models after launching the console run -reload! - -More information about irb can be found at: -link:http://www.rubycentral.com/pickaxe/irb.html - - -== dbconsole - -You can go to the command line of your database directly through rails -dbconsole. You would be connected to the database with the credentials -defined in database.yml. Starting the script without arguments will connect you -to the development database. Passing an argument will connect you to a different -database, like rails dbconsole production. Currently works for MySQL, -PostgreSQL and SQLite 3. - -== Description of Contents - -The default directory structure of a generated Ruby on Rails application: - - |-- app - | |-- controllers - | |-- helpers - | |-- mailers - | |-- models - | `-- views - | `-- layouts - |-- config - | |-- environments - | |-- initializers - | `-- locales - |-- db - |-- doc - |-- lib - | `-- tasks - |-- log - |-- public - | |-- images - | |-- javascripts - | `-- stylesheets - |-- script - |-- test - | |-- fixtures - | |-- functional - | |-- integration - | |-- performance - | `-- unit - |-- tmp - | |-- cache - | |-- pids - | |-- sessions - | `-- sockets - `-- vendor - `-- plugins - -app - Holds all the code that's specific to this particular application. - -app/controllers - Holds controllers that should be named like weblogs_controller.rb for - automated URL mapping. All controllers should descend from - ApplicationController which itself descends from ActionController::Base. - -app/models - Holds models that should be named like post.rb. Models descend from - ActiveRecord::Base by default. - -app/views - Holds the template files for the view that should be named like - weblogs/index.html.erb for the WeblogsController#index action. All views use - eRuby syntax by default. - -app/views/layouts - Holds the template files for layouts to be used with views. This models the - common header/footer method of wrapping views. In your views, define a layout - using the layout :default and create a file named default.html.erb. - Inside default.html.erb, call <% yield %> to render the view using this - layout. - -app/helpers - Holds view helpers that should be named like weblogs_helper.rb. These are - generated for you automatically when using generators for controllers. - Helpers can be used to wrap functionality for your views into methods. - -config - Configuration files for the Rails environment, the routing map, the database, - and other dependencies. - -db - Contains the database schema in schema.rb. db/migrate contains all the - sequence of Migrations for your schema. - -doc - This directory is where your application documentation will be stored when - generated using rake doc:app - -lib - Application specific libraries. Basically, any kind of custom code that - doesn't belong under controllers, models, or helpers. This directory is in - the load path. - -public - The directory available for the web server. Contains subdirectories for - images, stylesheets, and javascripts. Also contains the dispatchers and the - default HTML files. This should be set as the DOCUMENT_ROOT of your web - server. - -script - Helper scripts for automation and generation. - -test - Unit and functional tests along with fixtures. When using the rails generate - command, template test files will be generated for you and placed in this - directory. - -vendor - External libraries that the application depends on. Also includes the plugins - subdirectory. If the app has frozen rails, those gems also go here, under - vendor/rails/. This directory is in the load path. diff --git a/README.md b/README.md new file mode 100644 index 000000000..a58dc6dc8 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +RosaLab ABF +=========== + +A distributed environment to build distributions, supporting all steps from managing source code to creating ISO images. If you have any problems or requests please contact +[support](https://abf.rosalinux.ru/contact). + +**Note: This Documentation is in a beta state. Breaking changes may occur.** + +* [API](http://abf-doc.rosalinux.ru/abf/api/) +* [Integration with FileStore (.abf.yml)](http://abf-doc.rosalinux.ru/abf/file_store_integration/) +* [ISO build environment](http://abf-doc.rosalinux.ru/abf/iso_build/) +* [Package build environment](http://abf-doc.rosalinux.ru/abf/scripts/) +* [Deployment](http://abf-doc.rosalinux.ru/abf/deployment/) \ No newline at end of file diff --git a/app/controllers/api/v1/issues_controller.rb b/app/controllers/api/v1/issues_controller.rb new file mode 100644 index 000000000..6f0986a87 --- /dev/null +++ b/app/controllers/api/v1/issues_controller.rb @@ -0,0 +1,108 @@ +# -*- encoding : utf-8 -*- +class Api::V1::IssuesController < Api::V1::BaseController + respond_to :json + + before_filter :authenticate_user! + skip_before_filter :authenticate_user!, :only => [:show] if APP_CONFIG['anonymous_access'] + + load_and_authorize_resource :group, :only => :group_index + load_resource :project + load_and_authorize_resource :issue, :through => :project, :find_by => :serial_id, :only => [:show, :update, :destroy, :create, :index] + + def index + @issues = @project.issues + render_issues_list + end + + def all_index + project_ids = get_all_project_ids Project.accessible_by(current_ability, :membered).uniq.pluck(:id) + @issues = Issue.where('issues.project_id IN (?)', project_ids) + render_issues_list + end + + def user_index + project_ids = get_all_project_ids current_user.projects.select('distinct projects.id').pluck(:id) + @issues = Issue.where('issues.project_id IN (?)', project_ids) + render_issues_list + end + + def group_index + project_ids = @group.projects.select('distinct projects.id').pluck(:id) + @issues = Issue.where(:project_id => project_ids) + render_issues_list + end + + def show + respond_with @issue + end + + def create + @issue.user = current_user + create_subject @issue + end + + def update + update_subject @issue + end + + def destroy + destroy_subject @issue + end + + private + + def render_issues_list + @issues = @issues.includes(:user, :assignee, :labels).without_pull_requests + if params[:status] == 'closed' + @issues = @issues.closed + else + @issues = @issues.opened + end + + if action_name == 'index' && params[:assignee].present? + case params[:assignee] + when 'none' + @issues = @issues.where(:assigned_id => nil) + when '*' + @issues = @issues.where('assigned_id IS NOT NULL') + else + @issues = @issues.where('assignees_issues.uname = ?', params[:assignee]) + end + end + + if %w[all_index user_index group_index].include?(action_name) + case params[:filter] + when 'created' + @issues = @issues.where(:user_id => current_user) + when 'all' + else + @issues = @issues.where(:assignee_id => current_user) + end + else + @issues.where('users.uname = ?', params[:creator]) if params[:creator].present? + end + + if params[:labels].present? + labels = params[:labels].split(',').map {|e| e.strip}.select {|e| e.present?} + @issues = @issues.where('labels.name IN (?)', labels) + end + + sort = params[:sort] == 'updated' ? 'issues.updated_at' : 'issues.created_at' + direction = params[:direction] == 'asc' ? 'ASC' : 'DESC' + @issues = @issues.order("#{sort} #{direction}") + + @issues = @issues.where('created_at >= to_timestamp(?)', params[:since]) if params[:since] =~ /\A\d+\z/ + @issues.paginate(paginate_params) + respond_with @issues + end + + def get_all_project_ids default_project_ids + project_ids = [] + if ['created', 'all'].include? params[:filter] + # add own issues + project_ids = Project.accessible_by(current_ability, :show).joins(:issues). + where(:issues => {:user_id => current_user.id}).uniq.pluck('projects.id') + end + project_ids |= default_project_ids + end +end diff --git a/app/controllers/projects/projects_controller.rb b/app/controllers/projects/projects_controller.rb index 4c76cbbb4..23ff01ec9 100644 --- a/app/controllers/projects/projects_controller.rb +++ b/app/controllers/projects/projects_controller.rb @@ -72,7 +72,7 @@ class Projects::ProjectsController < Projects::BaseController redirect_to forked, :notice => t("flash.project.forked") else flash[:warning] = t("flash.project.fork_error") - flash[:error] = forked.errors.full_messages + flash[:error] = forked.errors.full_messages.join("\n") redirect_to @project end end diff --git a/app/controllers/projects/pull_requests_controller.rb b/app/controllers/projects/pull_requests_controller.rb index c53bea847..c1d5e4d45 100644 --- a/app/controllers/projects/pull_requests_controller.rb +++ b/app/controllers/projects/pull_requests_controller.rb @@ -115,9 +115,12 @@ class Projects::PullRequestsController < Projects::BaseController end def autocomplete_to_project - items = Project.accessible_by(current_ability, :membered) | @project.ancestors - term = Regexp.new(Regexp.escape params[:term].downcase) - items.select! {|e| term.match(e.name_with_owner.downcase) && e.repo.branches.count > 0} + items = [] + term = params[:term].to_s.strip.downcase + [Project.accessible_by(current_ability, :membered), @project.ancestors].each do |p| + items.concat p.by_owner_and_name(term) + end + items = items.uniq{|i| i.id}.select{|e| e.repo.branches.count > 0} render :json => json_for_autocomplete_base(items) end @@ -129,7 +132,7 @@ class Projects::PullRequestsController < Projects::BaseController def json_for_autocomplete_base items items.collect do |project| - hash = {"id" => project.id.to_s, "label" => project.name_with_owner, "value" => project.name_with_owner} + hash = {:id => project.id.to_s, :label => project.name_with_owner, :value => project.name_with_owner} hash[:get_refs_url] = project_refs_list_path(project) hash end diff --git a/app/models/ability.rb b/app/models/ability.rb index 03dc3311b..845d834f8 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -148,7 +148,8 @@ class Ability # Shared cannot rights for all users (registered, admin) cannot :destroy, Platform, :platform_type => 'personal' - cannot [:create, :destroy, :edit, :update, :add_project, :remove_project], Repository, :platform => {:platform_type => 'personal'} + cannot [:create, :destroy], Repository, :platform => {:platform_type => 'personal'}, :name => 'main' + cannot [:remove_members, :remove_member, :add_member], Repository, :platform => {:platform_type => 'personal'} cannot :clear, Platform, :platform_type => 'main' cannot :destroy, Issue diff --git a/app/models/collaborator.rb b/app/models/collaborator.rb index 8b1f1b412..ee9d73421 100644 --- a/app/models/collaborator.rb +++ b/app/models/collaborator.rb @@ -110,6 +110,7 @@ class Collaborator def destroy relation.try(:destroy) + @actor.check_assigned_issues @project end def attributes diff --git a/app/models/comment.rb b/app/models/comment.rb index 3650af49f..88913e613 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -142,6 +142,7 @@ class Comment < ActiveRecord::Base case when item.is_a?(GitHook) elements = commits + opts = {} when item.is_a?(Issue) elements = [[item, item.title], [item, item.body]] opts = {:created_from_issue_id => item.id} diff --git a/app/models/key_pair.rb b/app/models/key_pair.rb index ca8a3fe8c..e6bb7a246 100644 --- a/app/models/key_pair.rb +++ b/app/models/key_pair.rb @@ -21,9 +21,7 @@ class KeyPair < ActiveRecord::Base protected def check_keys - tmp = "#{APP_CONFIG['root_path']}/tmp" - system "sudo chown `whoami` #{tmp} && chmod 1777 #{tmp}" - dir = Dir.mktmpdir('keys-', tmp) + dir = Dir.mktmpdir('keys-', '/tmp') begin %w(pubring secring).each do |kind| filename = "#{dir}/#{kind}" diff --git a/app/models/platform.rb b/app/models/platform.rb index 29d4f8d2f..7c4d425be 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -19,7 +19,6 @@ class Platform < ActiveRecord::Base has_many :mass_builds validates :description, :presence => true - validates :owner, :presence => true validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validates :name, :uniqueness => {:case_sensitive => false}, :presence => true, :format => { :with => /\A[a-zA-Z0-9_\-\.]+\z/ } validates :distrib_type, :presence => true, :inclusion => {:in => APP_CONFIG['distr_types']} diff --git a/app/models/project.rb b/app/models/project.rb index 6bd70f7d4..b9794aee1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -29,11 +29,18 @@ class Project < ActiveRecord::Base validates :name, :uniqueness => {:scope => [:owner_id, :owner_type], :case_sensitive => false}, :presence => true, :format => {:with => /\A#{NAME_REGEXP}\z/, :message => I18n.t("activerecord.errors.project.uname")} - validates :owner, :presence => true validates :maintainer_id, :presence => true, :unless => :new_record? validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } validate :check_default_branch + # throws validation error message from ProjectToRepository model into Project model + validate do |project| + project.project_to_repositories.each do |p_to_r| + next if p_to_r.valid? + p_to_r.errors.full_messages.each{ |msg| errors[:base] << msg } + end + errors.delete :project_to_repositories + end attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki, :maintainer_id, :publish_i686_into_x86_64 attr_readonly :name, :owner_id, :owner_type @@ -42,6 +49,10 @@ class Project < ActiveRecord::Base scope :search_order, order("CHAR_LENGTH(#{table_name}.name) ASC") scope :search, lambda {|q| by_name("%#{q.to_s.strip}%")} scope :by_name, lambda {|name| where("#{table_name}.name ILIKE ?", name) if name.present?} + scope :by_owner_and_name, lambda { |*params| + term = params.map(&:strip).join('/').downcase + where("lower(concat(owner_uname, '/', name)) ILIKE ?", "%#{term}%") if term.present? + } scope :by_visibilities, lambda {|v| where(:visibility => v)} scope :opened, where(:visibility => 'open') scope :package, where(:is_package => true) @@ -59,6 +70,7 @@ class Project < ActiveRecord::Base } before_validation :truncate_name, :on => :create + before_save lambda { self.owner_uname = owner.uname if owner_uname.blank? || owner_id_changed? || owner_type_changed? } before_create :set_maintainer after_save :attach_to_personal_repository after_update :set_new_git_head @@ -71,10 +83,8 @@ class Project < ActiveRecord::Base class << self def find_by_owner_and_name(owner_name, project_name) - owner = User.find_by_uname(owner_name) || Group.find_by_uname(owner_name) || User.by_uname(owner_name).first || Group.by_uname(owner_name).first and - scoped = where(:owner_id => owner.id, :owner_type => owner.class) and - scoped.find_by_name(project_name) || scoped.by_name(project_name).first - # owner.projects.find_by_name(project_name) || owner.projects.by_name(project_name).first # TODO force this work? + where(:owner_uname => owner_name, :name => project_name).first || + by_owner_and_name(owner_name, project_name).first end def find_by_owner_and_name!(owner_name, project_name) @@ -82,6 +92,10 @@ class Project < ActiveRecord::Base end end + def name_with_owner + "#{owner_uname || owner.uname}/#{name}" + end + def to_param name end @@ -255,11 +269,11 @@ class Project < ActiveRecord::Base end def attach_to_personal_repository - owner_rep = self.owner.personal_repository + owner_repos = self.owner.personal_platform.repositories if is_package - repositories << owner_rep unless repositories.exists?(:id => owner_rep) + repositories << self.owner.personal_repository unless repositories.exists?(:id => owner_repos.pluck(:id)) else - repositories.delete owner_rep + repositories.delete owner_repos end end diff --git a/app/models/project_to_repository.rb b/app/models/project_to_repository.rb index 16035ce3e..a1f9c5327 100644 --- a/app/models/project_to_repository.rb +++ b/app/models/project_to_repository.rb @@ -7,12 +7,12 @@ class ProjectToRepository < ActiveRecord::Base after_destroy lambda { project.destroy_project_from_repository(repository) }, :unless => lambda {Thread.current[:skip]} - validate :one_project_in_platform_repositories + validate :one_project_in_platform_repositories, :on => :create protected def one_project_in_platform_repositories - errors.add(:project, 'should be one in platform') if Project.joins(:repositories => :platform). - where('platforms.id = ?', repository.platform_id).by_name(project.name).count > 0 + errors.add(:base, I18n.t('activerecord.errors.project_to_repository.project')) if Project.joins(:repositories => :platform). + where('platforms.id = ?', repository.platform_id).by_name(project.name).exists? end end diff --git a/app/models/relation.rb b/app/models/relation.rb index 2ce5d0fa4..58c54b277 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -34,7 +34,11 @@ class Relation < ActiveRecord::Base def self.remove_member(member, target) return false if target.respond_to?(:owner) && target.owner == member - Relation.by_actor(member).by_target(target).each{|r| r.destroy} + res = Relation.by_actor(member).by_target(target).each{|r| r.destroy} + if member.is_a?(User) && ['Project', 'Group'].include?(target.class.name) + member.check_assigned_issues target + end + res end protected diff --git a/app/models/repository.rb b/app/models/repository.rb index 23a4234d6..5a7968cab 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -17,7 +17,7 @@ class Repository < ActiveRecord::Base scope :recent, order("#{table_name}.name ASC") - before_destroy :detele_directory, :unless => lambda {Thread.current[:skip]} + before_destroy :detele_directory attr_accessible :name, :description, :publish_without_qa attr_readonly :name, :platform_id diff --git a/app/models/ssh_key.rb b/app/models/ssh_key.rb index a2c615585..ec09df1ce 100644 --- a/app/models/ssh_key.rb +++ b/app/models/ssh_key.rb @@ -22,7 +22,7 @@ class SshKey < ActiveRecord::Base def set_fingerprint return false unless key - file = Tempfile.new('key_file', "#{APP_CONFIG['root_path']}/tmp") + file = Tempfile.new('key_file', '/tmp') filename = file.path begin file.puts key diff --git a/app/models/user.rb b/app/models/user.rb index 71854e991..b7d9a498b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,6 +28,7 @@ class User < Avatar has_many :own_projects, :as => :owner, :class_name => 'Project', :dependent => :destroy has_many :own_groups, :foreign_key => :owner_id, :class_name => 'Group', :dependent => :destroy has_many :own_platforms, :as => :owner, :class_name => 'Platform', :dependent => :destroy + has_many :assigned_issues, :foreign_key => :assignee_id, :class_name => 'Issue', :dependent => :nullify has_many :key_pairs has_many :ssh_keys, :dependent => :destroy @@ -141,6 +142,19 @@ class User < Avatar raise "unknown user #{self.uname} roles #{roles}" end + def check_assigned_issues target + if target.is_a? Project + assigned_issues.where(:project_id => target.id).update_all(:assignee_id => nil) + else + ability = Ability.new self + project_ids = Project.accessible_by(ability, :membered).uniq.pluck(:id) + + issues = assigned_issues + issues = issues.where('project_id not in (?)', project_ids) if project_ids.present? + issues.update_all(:assignee_id => nil) + end + end + protected def target_roles target diff --git a/app/views/api/v1/issues/_issue.json.jbuilder b/app/views/api/v1/issues/_issue.json.jbuilder new file mode 100644 index 000000000..7db24740b --- /dev/null +++ b/app/views/api/v1/issues/_issue.json.jbuilder @@ -0,0 +1,11 @@ +json.number issue.serial_id +json.(issue, :title, :status) +json.labels issue.labels do |json_labels, label| + json.partial! 'label', :label => label, :json => json_labels +end +json.assignee do |json_assignee| + json.partial! 'api/v1/shared/member', :member => issue.assignee, :tag => json_assignee +end if issue.assignee + +json.url api_v1_project_issue_path(issue.project.id, issue.serial_id, :format => :json) + diff --git a/app/views/api/v1/issues/_label.json.jbuilder b/app/views/api/v1/issues/_label.json.jbuilder new file mode 100644 index 000000000..fdee26e0d --- /dev/null +++ b/app/views/api/v1/issues/_label.json.jbuilder @@ -0,0 +1 @@ +json.(label, :name, :color) diff --git a/app/views/api/v1/issues/index.json.jbuilder b/app/views/api/v1/issues/index.json.jbuilder new file mode 100644 index 000000000..85e2ffb00 --- /dev/null +++ b/app/views/api/v1/issues/index.json.jbuilder @@ -0,0 +1,11 @@ +json.issues @issues do |json, issue| + json.partial! 'issue', :issue => issue, :json => json + json.issue issue.body + json.partial! 'api/v1/shared/owner', :owner => issue.user + json.closed_at issue.closed_at.to_i + json.closed_by do |json_user| + json.partial! 'api/v1/shared/member', :member => issue.closer, :tag => json_user + end if issue.closer + json.created_at issue.created_at.to_i + json.updated_at issue.updated_at.to_i +end diff --git a/app/views/api/v1/issues/show.json.jbuilder b/app/views/api/v1/issues/show.json.jbuilder new file mode 100644 index 000000000..4cff5fbb7 --- /dev/null +++ b/app/views/api/v1/issues/show.json.jbuilder @@ -0,0 +1,11 @@ +json.issue do |json| + json.partial! 'issue', :issue => @issue, :json => json + json.issue @issue.body + json.partial! 'api/v1/shared/owner', :owner => @issue.user + json.closed_at @issue.closed_at.to_i + json.closed_by do |json_user| + json.partial! 'api/v1/shared/member', :member => @issue.closer, :tag => json_user + end if @issue.closer + json.created_at @issue.created_at.to_i + json.updated_at @issue.updated_at.to_i +end diff --git a/app/views/platforms/key_pairs/_new.html.haml b/app/views/platforms/key_pairs/_new.html.haml index b740fe218..ff0cff09a 100644 --- a/app/views/platforms/key_pairs/_new.html.haml +++ b/app/views/platforms/key_pairs/_new.html.haml @@ -1,5 +1,3 @@ -= render 'platforms/base/sidebar' - %h3= t("layout.key_pairs.header") = form_for :key_pair, :url => platform_key_pairs_path(@platform), :method => :post, :html => { :class => :form } do |f| diff --git a/app/views/platforms/key_pairs/index.html.haml b/app/views/platforms/key_pairs/index.html.haml index b04743a34..1d1959d5e 100644 --- a/app/views/platforms/key_pairs/index.html.haml +++ b/app/views/platforms/key_pairs/index.html.haml @@ -1,2 +1,6 @@ +- set_meta_tags :title => [title_object(@platform), t('layout.key_pairs.header')] += render 'platforms/base/submenu' += render 'platforms/base/sidebar' + = render 'new' if can? :edit, @platform = render 'list' diff --git a/app/views/platforms/repositories/_form.html.haml b/app/views/platforms/repositories/_form.html.haml index e8e3a1b91..f054218b7 100644 --- a/app/views/platforms/repositories/_form.html.haml +++ b/app/views/platforms/repositories/_form.html.haml @@ -15,7 +15,7 @@ .rightside = link_to t('layout.repositories.regenerate_metadata').split.first, regenerate_metadata_platform_repository_path(@platform, @repository), :method => :put, :confirm => t('layout.confirm'), :class => :button -.hr{:style => 'padding-bottom:20px;'} + .hr{:style => 'padding-bottom:20px;'} .both .button_block diff --git a/app/views/platforms/repositories/edit.html.haml b/app/views/platforms/repositories/edit.html.haml index 5a9f1b232..e9fff3fe4 100644 --- a/app/views/platforms/repositories/edit.html.haml +++ b/app/views/platforms/repositories/edit.html.haml @@ -8,9 +8,10 @@ = render "form", :f => f %br -= render "shared/members_table", - :remove_members_path => remove_members_platform_repository_path(@platform, @repository), - :remove_member_path => remove_member_platform_repository_path(@platform, @repository), - :add_member_path => add_member_platform_repository_path(@platform, @repository), - :members => @members, - :editable_object => @repository +- if @platform.main? + = render "shared/members_table", + :remove_members_path => remove_members_platform_repository_path(@platform, @repository), + :remove_member_path => remove_member_platform_repository_path(@platform, @repository), + :add_member_path => add_member_platform_repository_path(@platform, @repository), + :members => @members, + :editable_object => @repository diff --git a/app/views/projects/git/base/_fork.html.haml b/app/views/projects/git/base/_fork.html.haml index be9cf54d4..98d55a301 100644 --- a/app/views/projects/git/base/_fork.html.haml +++ b/app/views/projects/git/base/_fork.html.haml @@ -14,5 +14,5 @@ - Group.can_own_project(current_user).each do |group| =render 'choose_fork', :owner => group %hr.bootstrap -- if can? :create, @project.build_lists.new +- if @project.is_package && can?(:create, @project.build_lists.new) .r{:style => "display: block"}= link_to t('layout.projects.new_build_list'), new_project_build_list_path(@project), :class => 'button' diff --git a/config/locales/models/project_to_repository.en.yml b/config/locales/models/project_to_repository.en.yml new file mode 100644 index 000000000..553d2e8f3 --- /dev/null +++ b/config/locales/models/project_to_repository.en.yml @@ -0,0 +1,5 @@ +en: + activerecord: + errors: + project_to_repository: + project: Project already exists in platform \ No newline at end of file diff --git a/config/locales/models/project_to_repository.ru.yml b/config/locales/models/project_to_repository.ru.yml new file mode 100644 index 000000000..503a54f54 --- /dev/null +++ b/config/locales/models/project_to_repository.ru.yml @@ -0,0 +1,5 @@ +ru: + activerecord: + errors: + project_to_repository: + project: Проект уже присутствует в платформе diff --git a/config/locales/models/repository.en.yml b/config/locales/models/repository.en.yml index 11dcae4db..3330fd0e9 100644 --- a/config/locales/models/repository.en.yml +++ b/config/locales/models/repository.en.yml @@ -36,7 +36,7 @@ en: update_error: Unable to update repository destroyed: Repository deleted project_added: Project added to repository - project_not_added: Project adding error. A project with such name already exists in this repository. Remove the old project first + project_not_added: Project adding error. A project with such name already exists in one repository of platform. Remove the old project first project_removed: Project deleted project_not_removed: Unable to delete project from repository clear: Platform successfully cleared! diff --git a/config/locales/models/repository.ru.yml b/config/locales/models/repository.ru.yml index f5e5a58fa..257926dbc 100644 --- a/config/locales/models/repository.ru.yml +++ b/config/locales/models/repository.ru.yml @@ -36,7 +36,7 @@ ru: update_error: Не удалось обновить репозиторий destroyed: Репозиторий успешно удален project_added: Проект добавлен к репозиторию - project_not_added: Не удалось добавить проект. В этом репозитории уже есть проект с таким именем. Сначала нужно удалить старый проект + project_not_added: Не удалось добавить проект. В одном из репозиториев платформы уже есть проект с таким именем. Сначала нужно удалить старый проект project_removed: Проект удален из репозитория project_not_removed: Не удалось удалить проект из репозитория clear: Платформа успешно очищена! diff --git a/config/routes.rb b/config/routes.rb index abaecad7c..6db1b9c87 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -58,6 +58,7 @@ Rosa::Application.routes.draw do put :update_member } resources :build_lists, :only => :index + resources :issues, :only => [:index, :create, :show, :update] end resources :users, :only => [:show] get 'user' => 'users#show_current_user' @@ -65,6 +66,7 @@ Rosa::Application.routes.draw do member { get :notifiers put :notifiers + get '/issues' => 'issues#user_index' } end resources :groups, :only => [:index, :show, :update, :create, :destroy] do @@ -73,6 +75,7 @@ Rosa::Application.routes.draw do put :add_member delete :remove_member put :update_member + get '/issues' => 'issues#group_index' } end resources :products, :only => [:show, :update, :create, :destroy] do @@ -82,6 +85,7 @@ Rosa::Application.routes.draw do put :cancel, :on => :member end #resources :ssh_keys, :only => [:index, :create, :destroy] + get 'issues' => 'issues#all_index' end end diff --git a/db/migrate/20130403202853_add_name_with_owner_to_project.rb b/db/migrate/20130403202853_add_name_with_owner_to_project.rb new file mode 100644 index 000000000..7f7cd58f2 --- /dev/null +++ b/db/migrate/20130403202853_add_name_with_owner_to_project.rb @@ -0,0 +1,22 @@ +class AddNameWithOwnerToProject < ActiveRecord::Migration + def up + add_column :projects, :owner_uname, :string + + execute <<-SQL + UPDATE projects SET owner_uname = owners.uname + FROM users as owners + WHERE projects.owner_type = 'User' AND projects.owner_id = owners.id + SQL + + execute <<-SQL + UPDATE projects SET owner_uname = owners.uname + FROM groups as owners + WHERE projects.owner_type = 'Group' AND projects.owner_id = owners.id + SQL + change_column :projects, :owner_uname, :string, :null => false + end + + def down + remove_column :projects, :owner_uname + end +end diff --git a/db/migrate/20130417162427_add_user_index_to_issue.rb b/db/migrate/20130417162427_add_user_index_to_issue.rb new file mode 100644 index 000000000..b11c42283 --- /dev/null +++ b/db/migrate/20130417162427_add_user_index_to_issue.rb @@ -0,0 +1,5 @@ +class AddUserIndexToIssue < ActiveRecord::Migration + def change + add_index :issues, :user_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 4df2709ff..7e58a8967 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,14 +11,14 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130412124536) do +ActiveRecord::Schema.define(:version => 20130417162427) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false t.string "kind" t.text "data" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "advisories", :force => true do |t| @@ -53,8 +53,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "arches", :force => true do |t| t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "arches", ["name"], :name => "index_arches_on_name", :unique => true @@ -63,8 +63,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.integer "user_id" t.string "provider" t.string "uid" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "authentications", ["provider", "uid"], :name => "index_authentications_on_provider_and_uid", :unique => true @@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.integer "level" t.integer "status" t.integer "build_list_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "version" end @@ -110,8 +110,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.integer "project_id" t.integer "arch_id" t.datetime "notified_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "is_circle", :default => false t.text "additional_repos" t.string "name" @@ -150,8 +150,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "commentable_type" t.integer "user_id" t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.decimal "commentable_id", :precision => 50, :scale => 0 t.integer "project_id" t.text "data" @@ -178,8 +178,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "controller" t.string "action" t.text "message" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "flash_notifies", :force => true do |t| @@ -193,8 +193,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "groups", :force => true do |t| t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "uname" t.integer "own_projects_count", :default => 0, :null => false t.text "description" @@ -219,14 +219,15 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "title" t.text "body" t.string "status", :default => "open" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "user_id" t.datetime "closed_at" t.integer "closed_by" end add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true + add_index "issues", ["user_id"], :name => "index_issues_on_user_id" create_table "key_pairs", :force => true do |t| t.text "public", :null => false @@ -297,14 +298,14 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "description" t.string "name", :null => false t.integer "parent_platform_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "released", :default => false, :null => false t.integer "owner_id" t.string "owner_type" t.string "visibility", :default => "open", :null => false t.string "platform_type", :default => "main", :null => false - t.string "distrib_type" + t.string "distrib_type", :null => false end add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false @@ -313,16 +314,16 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.integer "platform_id" t.string "login" t.string "password" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "user_id" end create_table "product_build_lists", :force => true do |t| t.integer "product_id" - t.integer "status", :default => 3, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "status", :default => 2, :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "project_id" t.string "project_version" t.string "commit_hash" @@ -341,8 +342,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "products", :force => true do |t| t.string "name", :null => false t.integer "platform_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "description" t.integer "project_id" t.string "params" @@ -357,8 +358,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "name" t.string "version" t.datetime "file_mtime" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "platform_id" end @@ -377,33 +378,34 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "project_to_repositories", :force => true do |t| t.integer "project_id" t.integer "repository_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "project_to_repositories", ["repository_id", "project_id"], :name => "index_project_to_repositories_on_repository_id_and_project_id", :unique => true create_table "projects", :force => true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "owner_id" t.string "owner_type" t.string "visibility", :default => "open" t.text "description" t.string "ancestry" t.boolean "has_issues", :default => true - t.boolean "has_wiki", :default => false t.string "srpm_file_name" - t.string "srpm_content_type" t.integer "srpm_file_size" t.datetime "srpm_updated_at" + t.string "srpm_content_type" + t.boolean "has_wiki", :default => false t.string "default_branch", :default => "master" t.boolean "is_package", :default => true, :null => false t.integer "average_build_time", :default => 0, :null => false t.integer "build_count", :default => 0, :null => false t.integer "maintainer_id" t.boolean "publish_i686_into_x86_64", :default => false + t.string "owner_uname", :null => false end add_index "projects", ["owner_id", "name", "owner_type"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false @@ -428,8 +430,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "token" t.boolean "approved", :default => false t.boolean "rejected", :default => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "interest" t.text "more" t.string "language" @@ -443,16 +445,16 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "actor_type" t.integer "target_id" t.string "target_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "role" end create_table "repositories", :force => true do |t| t.string "description", :null => false t.integer "platform_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "name", :null => false t.boolean "publish_without_qa", :default => true end @@ -466,8 +468,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.boolean "new_comment_reply", :default => true t.boolean "new_issue", :default => true t.boolean "issue_assign", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "new_comment_commit_owner", :default => true t.boolean "new_comment_commit_repo_owner", :default => true t.boolean "new_comment_commit_commentor", :default => true @@ -490,8 +492,8 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "subscribes", :force => true do |t| t.string "subscribeable_type" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "status", :default => true t.integer "project_id" t.decimal "subscribeable_id", :precision => 50, :scale => 0 @@ -499,21 +501,18 @@ ActiveRecord::Schema.define(:version => 20130412124536) do create_table "users", :force => true do |t| t.string "name" - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false + t.string "email", :default => "", :null => false + t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "ssh_key" t.string "uname" t.string "role" - t.string "language", :default => "en" - t.integer "own_projects_count", :default => 0, :null => false - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" + t.string "language", :default => "en" + t.integer "own_projects_count", :default => 0, :null => false t.text "professional_experience" t.string "site" t.string "company" @@ -522,11 +521,14 @@ ActiveRecord::Schema.define(:version => 20130412124536) do t.string "avatar_content_type" t.integer "avatar_file_size" t.datetime "avatar_updated_at" - t.integer "failed_attempts", :default => 0 + t.integer "failed_attempts", :default => 0 t.string "unlock_token" t.datetime "locked_at" + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "confirmation_sent_at" t.string "authentication_token" - t.integer "build_priority", :default => 50 + t.integer "build_priority", :default => 50 end add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token" diff --git a/lib/abf_worker/build_lists_publish_task_manager.rb b/lib/abf_worker/build_lists_publish_task_manager.rb index e8a9e88c7..0b0f51d52 100644 --- a/lib/abf_worker/build_lists_publish_task_manager.rb +++ b/lib/abf_worker/build_lists_publish_task_manager.rb @@ -246,7 +246,7 @@ module AbfWorker order(:updated_at) locked_ids = @redis.lrange(LOCKED_BUILD_LISTS, 0, -1) build_lists = build_lists.where('build_lists.id NOT IN (?)', locked_ids) unless locked_ids.empty? - build_lists = build_lists.limit(50) + build_lists = build_lists.limit(150) old_packages = {:sources => [], :binaries => {:x86_64 => [], :i586 => []}} diff --git a/lib/modules/models/owner.rb b/lib/modules/models/owner.rb index e88ac3f5f..395d30db1 100644 --- a/lib/modules/models/owner.rb +++ b/lib/modules/models/owner.rb @@ -5,12 +5,10 @@ module Modules extend ActiveSupport::Concern included do + validates :owner, :presence => true after_create lambda { relations.create :actor_id => owner.id, :actor_type => owner.class.to_s, :role => 'admin' } end - def name_with_owner - "#{owner.respond_to?(:uname) ? owner.uname : owner.name}/#{self.name}" - end end end end diff --git a/spec/controllers/api/v1/build_lists_controller_spec.rb b/spec/controllers/api/v1/build_lists_controller_spec.rb index fdb82b5dd..cb0e68149 100644 --- a/spec/controllers/api/v1/build_lists_controller_spec.rb +++ b/spec/controllers/api/v1/build_lists_controller_spec.rb @@ -480,8 +480,11 @@ describe Api::V1::BuildListsController do @user = FactoryGirl.create(:user) @group.actors.create :role => 'reader', :actor_id => @user.id, :actor_type => 'User' + old_path = @project.path @project.owner = @owner_group @project.save + # Move GIT repo into new folder + system "mkdir -p #{@project.path} && mv -f #{old_path}/* #{@project.path}/" @project.relations.create :role => 'reader', :actor_id => @member_group.id, :actor_type => 'Group' @project.relations.create :role => 'admin', :actor_id => @owner_group.id, :actor_type => 'Group' diff --git a/spec/controllers/api/v1/issues_controller_spec.rb b/spec/controllers/api/v1/issues_controller_spec.rb new file mode 100644 index 000000000..95082856a --- /dev/null +++ b/spec/controllers/api/v1/issues_controller_spec.rb @@ -0,0 +1,181 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Api::V1::IssuesController do + before(:all) do + stub_symlink_methods + stub_redis + any_instance_of(Project, :versions => ['v1.0', 'v2.0']) + + @issue = FactoryGirl.create(:issue) + @project = @issue.project + + @membered_issue = FactoryGirl.create(:issue) + @membered_project = @membered_issue.project + @membered_project.relations.create(:role => 'reader', :actor => @issue.user) + + @open_issue = FactoryGirl.create(:issue) + @open_project = @open_issue.project + + @own_hidden_project = FactoryGirl.create(:project, :owner => @issue.user) + @own_hidden_project.update_column :visibility, 'hidden' + @own_hidden_issue = FactoryGirl.create(:issue, :project => @own_hidden_project, :assignee => @issue.user) + + @hidden_issue = FactoryGirl.create(:issue) + @hidden_project = @hidden_issue.project + @hidden_project.update_column :visibility, 'hidden' + + @create_params = {:issue => {:title => 'title', :body => 'body'}, :project_id => @project.id, :format => :json} + @update_params = {:issue => {:title => 'new title'}, :project_id => @project.id, :id => @issue.serial_id, :format => :json} + end + + context 'read and accessible abilities' do + context 'for user' do + before(:each) do + http_login(@issue.user) + end + + it 'can show issue in own project' do + get :show, :project_id => @project.id, :id => @issue.serial_id, :format => :json + response.should be_success + end + + it 'can show issue in open project' do + get :show, :project_id => @open_project.id, :id => @open_issue.serial_id, :format => :json + response.should be_success + end + + it 'can show issue in own hidden project' do + get :show, :project_id => @own_hidden_project.id, :id => @own_hidden_issue.serial_id, :format => :json + response.should be_success + end + + it 'cant show issue in hidden project' do + get :show, :project_id => @hidden_project.id, :id => @hidden_issue.serial_id, :format => :json + response.status.should == 403 + end + + it 'should return three issues' do + get :all_index, :filter => 'all', :format => :json + assigns[:issues].should include(@issue) + assigns[:issues].should include(@own_hidden_issue) + assigns[:issues].should include(@membered_issue) + end + + it 'should return only assigned issue' do + http_login(@issue.user) + get :user_index, :format => :json + assigns[:issues].should include(@own_hidden_issue) + assigns[:issues].count.should == 1 + end + end + + context 'for anonymous user' do + it 'can show issue in open project', :anonymous_access => true do + get :show, :project_id => @project.id, :id => @issue.serial_id, :format => :json + response.should be_success + end + + it 'cant show issue in hidden project', :anonymous_access => true do + get :show, :project_id => @hidden_project.id, :id => @hidden_issue.serial_id, :format => :json + response.status.should == 403 + end + + it 'should not return any issues' do + get :all_index, :filter => 'all', :format => :json + response.status.should == 401 + end + end + end + + context 'create accessibility' do + context 'for user' do + before(:each) do + http_login(@issue.user) + @count = Issue.count + end + + it 'can create issue in own project' do + post :create, @create_params + Issue.count.should == @count+1 + end + + it 'can create issue in own hidden project' do + post :create, @create_params.merge(:project_id => @own_hidden_project.id) + Issue.count.should == @count+1 + end + + it 'can create issue in open project' do + post :create, @create_params.merge(:project_id => @open_project.id) + Issue.count.should == @count+1 + end + + it 'cant create issue in hidden project' do + post :create, @create_params.merge(:project_id => @hidden_project.id) + Issue.count.should == @count + end + end + + context 'for anonymous user' do + before(:each) do + @count = Issue.count + end + it 'cant create issue in project', :anonymous_access => true do + post :create, @create_params + Issue.count.should == @count + end + + it 'cant create issue in hidden project', :anonymous_access => true do + post :create, @create_params.merge(:project_id => @hidden_project.id) + Issue.count.should == @count + end + end + end + + context 'update accessibility' do + context 'for user' do + before(:each) do + http_login(@issue.user) + end + + it 'can update issue in own project' do + put :update, @update_params + @issue.reload.title.should == 'new title' + end + + it 'can update issue in own hidden project' do + put :update, @update_params.merge(:project_id => @own_hidden_project.id, :id => @own_hidden_issue.serial_id) + @own_hidden_issue.reload.title.should == 'new title' + end + + it 'cant update issue in open project' do + put :update, @update_params.merge(:project_id => @open_project.id, :id => @open_issue.serial_id) + @open_issue.reload.title.should_not == 'new title' + end + + it 'cant update issue in hidden project' do + put :update, @update_params.merge(:project_id => @hidden_project.id, :id => @hidden_issue.serial_id) + @hidden_issue.reload.title.should_not == 'title' + end + end + + context 'for anonymous user' do + before(:each) do + @count = Issue.count + end + it 'cant update issue in project', :anonymous_access => true do + put :update, @update_params + response.status.should == 401 + end + + it 'cant update issue in hidden project', :anonymous_access => true do + put :update, @update_params.merge(:project_id => @hidden_project.id, :id => @hidden_issue.serial_id) + response.status.should == 401 + end + end + end + after(:all) do + User.destroy_all + Platform.destroy_all + end +end diff --git a/spec/controllers/api/v1/repositories_controller_spec.rb b/spec/controllers/api/v1/repositories_controller_spec.rb index f1a11ed4c..0b6f2391e 100644 --- a/spec/controllers/api/v1/repositories_controller_spec.rb +++ b/spec/controllers/api/v1/repositories_controller_spec.rb @@ -99,12 +99,24 @@ shared_examples_for 'api repository user with writer rights' do it 'ensures that repository of main platform has been destroyed' do lambda { delete :destroy, :id => @repository.id, :format => :json }.should change{ Repository.count }.by(-1) end - it 'should not be able to perform destroy action for repository of personal platform' do - delete :destroy, :id => @personal_repository.id, :format => :json - response.should_not be_success + + context 'repository with name "main" of personal platform' do + # hook for "ActiveRecord::ActiveRecordError: name is marked as readonly" + before { Repository.where(:id => @personal_repository.id).update_all("name = 'main'") } + it 'should not be able to perform destroy action' do + delete :destroy, :id => @personal_repository.id, :format => :json + response.should_not be_success + end + it 'ensures that repository has not been destroyed' do + lambda { delete :destroy, :id => @personal_repository.id, :format => :json }.should_not change{ Repository.count } + end end - it 'ensures that repository of personal platform has not been destroyed' do - lambda { delete :destroy, :id => @personal_repository.id, :format => :json }.should_not change{ Repository.count } + it 'should be able to perform destroy action for repository with name not "main" of personal platform' do + delete :destroy, :id => @personal_repository.id, :format => :json + response.should be_success + end + it 'ensures that repository with name not "main" of personal platform has been destroyed' do + lambda { delete :destroy, :id => @personal_repository.id, :format => :json }.should change{ Repository.count }.by(-1) end end @@ -296,9 +308,11 @@ describe Api::V1::RepositoriesController do before(:each) do @user = FactoryGirl.create(:user) http_login(@user) - platform = @repository.platform - platform.owner = @user; platform.save - @repository.platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + [@repository, @personal_repository].each do |repository| + platform = repository.platform + platform.owner = @user; platform.save + repository.platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + end end it_should_behave_like 'api repository user with reader rights' diff --git a/spec/controllers/platforms/repositories_controller_spec.rb b/spec/controllers/platforms/repositories_controller_spec.rb index c4481c9ea..80cca3236 100644 --- a/spec/controllers/platforms/repositories_controller_spec.rb +++ b/spec/controllers/platforms/repositories_controller_spec.rb @@ -1,14 +1,6 @@ # -*- encoding : utf-8 -*- require 'spec_helper' -shared_examples_for 'not destroy personal repository' do - it 'should not be able to destroy personal repository' do - lambda { delete :destroy, :id => @personal_repository.id, :platform_id => - @personal_repository.platform.id}.should change{ Repository.count }.by(0) - response.should redirect_to(redirect_path) - end -end - shared_examples_for 'user with change projects in repository rights' do it 'should be able to see add_project page' do @@ -90,12 +82,16 @@ shared_examples_for 'registered user or guest' do end it 'should not be able to destroy repository in main platform' do - delete :destroy, :id => @repository.id + delete :destroy, :id => @repository.id, :platform_id => @platform.id response.should redirect_to(redirect_path) lambda { delete :destroy, :id => @repository.id }.should_not change{ Repository.count }.by(-1) end - it_should_behave_like 'not destroy personal repository' + it 'should not be able to destroy personal repository' do + lambda { delete :destroy, :id => @personal_repository.id, :platform_id => @personal_repository.platform.id}. + should change{ Repository.count }.by(0) + response.should redirect_to(redirect_path) + end end shared_examples_for 'registered user' do @@ -131,7 +127,7 @@ shared_examples_for 'platform admin user' do end it 'should be able to destroy repository in main platform' do - lambda { delete :destroy, :id => @repository.id }.should change{ Repository.count }.by(-1) + lambda { delete :destroy, :id => @repository.id, :platform_id => @platform.id }.should change{ Repository.count }.by(-1) response.should redirect_to(platform_repositories_path(@repository.platform)) end @@ -163,10 +159,21 @@ shared_examples_for 'platform admin user' do @repository.members.should_not include(@another_user, another_user2) end - it_should_behave_like 'user with change projects in repository rights' - it_should_behave_like 'not destroy personal repository' do - let(:redirect_path) { forbidden_path } + it 'should not be able to destroy personal repository with name "main"' do + # hook for "ActiveRecord::ActiveRecordError: name is marked as readonly" + Repository.where(:id => @personal_repository.id).update_all("name = 'main'") + lambda { delete :destroy, :id => @personal_repository.id, :platform_id => @personal_repository.platform.id}. + should change{ Repository.count }.by(0) + response.should redirect_to(forbidden_path) end + + it 'should be able to destroy personal repository with name not "main"' do + lambda { delete :destroy, :id => @personal_repository.id, :platform_id => @personal_repository.platform.id}. + should change{ Repository.count }.by(-1) + response.should redirect_to(platform_repositories_path(@personal_repository.platform)) + end + + it_should_behave_like 'user with change projects in repository rights' end describe Platforms::RepositoriesController do @@ -234,6 +241,8 @@ describe Platforms::RepositoriesController do context 'for platform owner user' do before(:each) do @user = @repository.platform.owner + platform = @personal_repository.platform + platform.owner = @user; platform.save set_session_for(@user) end @@ -242,7 +251,9 @@ describe Platforms::RepositoriesController do context 'for platform member user' do before(:each) do - @platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + [@repository, @personal_repository].each do |repo| + repo.platform.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + end end it_should_behave_like 'platform admin user' @@ -250,7 +261,9 @@ describe Platforms::RepositoriesController do context 'for repository member user' do before(:each) do - @repository.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + [@repository, @personal_repository].each do |repo| + repo.relations.create!(:actor_type => 'User', :actor_id => @user.id, :role => 'admin') + end end it_should_behave_like 'registered user' diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb index 1148f84fb..1a5053937 100644 --- a/spec/models/cancan_spec.rb +++ b/spec/models/cancan_spec.rb @@ -3,12 +3,12 @@ require 'spec_helper' require "cancan/matchers" def admin_create - @admin = FactoryGirl.create(:admin) + @admin = FactoryGirl.create(:admin) @ability = Ability.new(@admin) end def user_create - @user = FactoryGirl.create(:user) + @user = FactoryGirl.create(:user) @ability = Ability.new(@user) end @@ -17,47 +17,51 @@ def guest_create end describe CanCan do - - let(:personal_platform) { FactoryGirl.create(:platform, :platform_type => 'personal') } - let(:personal_repository) { FactoryGirl.create(:personal_repository) } - let(:open_platform) { FactoryGirl.create(:platform, :visibility => 'open') } - let(:hidden_platform) { FactoryGirl.create(:platform, :visibility => 'hidden') } - let(:register_request) { FactoryGirl.create(:register_request) } + let(:open_platform) { FactoryGirl.create(:platform, :visibility => 'open') } before(:each) do stub_symlink_methods end - context 'Site admin' do - before(:each) do - admin_create - end + context 'Site admin' do + let(:personal_platform) { FactoryGirl.create(:platform, :platform_type => 'personal') } + let(:personal_repository_main) { FactoryGirl.create(:personal_repository, :name => 'main') } + let(:personal_repository) { FactoryGirl.create(:personal_repository) } + before(:each) do + admin_create + end - it 'should manage all' do - #(@ability.can? :manage, :all).should be_true - @ability.should be_able_to(:manage, :all) - end + it 'should manage all' do + #(@ability.can? :manage, :all).should be_true + @ability.should be_able_to(:manage, :all) + end - it 'should not be able to destroy personal platforms' do - @ability.should_not be_able_to(:destroy, personal_platform) - end + it 'should not be able to destroy personal platforms' do + @ability.should_not be_able_to(:destroy, personal_platform) + end - it 'should not be able to destroy personal repositories' do - @ability.should_not be_able_to(:destroy, personal_repository) - end - end + it 'should not be able to destroy personal repositories with name "main"' do + @ability.should_not be_able_to(:destroy, personal_repository_main) + end + it 'should be able to destroy personal repositories with name not "main"' do + @ability.should be_able_to(:destroy, personal_repository) + end + end - context 'Site guest' do - before(:each) do - guest_create - end + context 'Site guest' do + let(:hidden_platform) { FactoryGirl.create(:platform, :visibility => 'hidden') } + let(:register_request) { FactoryGirl.create(:register_request) } + + before(:each) do + guest_create + end it 'should not be able to read open platform' do - @ability.should_not be_able_to(:read, open_platform) + @ability.should_not be_able_to(:read, open_platform) end it 'should not be able to read hidden platform' do - @ability.should_not be_able_to(:read, hidden_platform) + @ability.should_not be_able_to(:read, hidden_platform) end [:publish, :cancel, :reject_publish, :create_container].each do |action| @@ -78,10 +82,10 @@ describe CanCan do @ability.should_not be_able_to(:destroy, register_request) end - pending 'should be able to register new user' do # while self registration is closed - @ability.should be_able_to(:create, User) - end - end + pending 'should be able to register new user' do # while self registration is closed + @ability.should be_able_to(:create, User) + end + end context 'Site user' do before(:each) do diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 79c605b94..1777fcc92 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -41,8 +41,8 @@ describe Issue do @project = FactoryGirl.create(:project, :owner => @user) @group = FactoryGirl.create(:group) - reader = FactoryGirl.create :user - @group.actors.create(:actor_type => 'User', :actor_id => reader.id, :role => 'reader') + @reader = FactoryGirl.create :user + @group.actors.create(:actor_type => 'User', :actor_id => @reader.id, :role => 'reader') end it 'should send an e-mail to all members of the admin group' do @@ -65,6 +65,32 @@ describe Issue do create_issue(@stranger) ActionMailer::Base.deliveries.count.should == 1 # 1 project owner end + + it 'should reset issue assignee after remove him from group' do + @project.relations.create!(:actor_type => 'Group', :actor_id => @group.id, :role => 'reader') + create_issue(@group.owner) + @issue.update_column :assignee_id, @reader.id + @group.remove_member @reader + @issue.reload.assignee_id.should == nil + end + + it 'should not reset issue assignee' do + @project.relations.create!(:actor_type => 'Group', :actor_id => @group.id, :role => 'reader') + @project.relations.create!(:actor_type => 'User', :actor_id => @reader.id, :role => 'reader') + create_issue(@group.owner) + @issue.update_column :assignee_id, @reader.id + @group.remove_member @reader + @issue.reload.assignee_id.should == @reader.id + end + + it 'should reset issue assignee after remove him from project' do + @project.relations.create!(:actor_type => 'User', :actor_id => @reader.id, :role => 'reader') + create_issue(@reader) + @issue.update_column :assignee_id, @reader.id + @project.remove_member @reader # via api + @issue.reload.assignee_id.should == nil + end + end context 'Group project' do diff --git a/spec/models/platform_spec.rb b/spec/models/platform_spec.rb index 20b1c9d2e..13ec8a3de 100644 --- a/spec/models/platform_spec.rb +++ b/spec/models/platform_spec.rb @@ -2,48 +2,49 @@ require 'spec_helper' describe Platform do - before(:all) do - stub_symlink_methods - Platform.delete_all - User.delete_all - init_test_root - # Need for validate_uniqueness_of check - FactoryGirl.create(:platform) + before { stub_symlink_methods } + + context 'ensures that validations and associations exist' do + before do + # Need for validate_uniqueness_of check + FactoryGirl.create(:platform) + end + + it { should belong_to(:owner) } + it { should have_many(:members)} + it { should have_many(:repositories)} + it { should have_many(:products)} + + it { should validate_presence_of(:name)} + it { should validate_uniqueness_of(:name).case_insensitive } + it { should allow_value('Basic_platform-name-1234').for(:name) } + it { should_not allow_value('.!').for(:name) } + it { should validate_presence_of(:description) } + it { should validate_presence_of(:distrib_type) } + it { should validate_presence_of(:visibility) } + + Platform::VISIBILITIES.each do |value| + it {should allow_value(value).for(:visibility)} + end + it {should_not allow_value('custom_status').for(:visibility)} + + it { should have_readonly_attribute(:name) } + it { should have_readonly_attribute(:distrib_type) } + it { should have_readonly_attribute(:parent_platform_id) } + it { should have_readonly_attribute(:platform_type) } + + it { should_not allow_mass_assignment_of(:repositories) } + it { should_not allow_mass_assignment_of(:products) } + it { should_not allow_mass_assignment_of(:members) } + it { should_not allow_mass_assignment_of(:parent) } + + it {should_not allow_value("How do you do...\nmy_platform").for(:name)} end - it { should belong_to(:owner) } - it { should have_many(:members)} - it { should have_many(:repositories)} - it { should have_many(:products)} - - it { should validate_presence_of(:name)} - it { should validate_uniqueness_of(:name).case_insensitive } - it { should validate_format_of(:name).with('Basic_platform-name-1234') } - it { should validate_format_of(:name).not_with('.!') } - it { should validate_presence_of(:description) } - it { should validate_presence_of(:distrib_type) } - it { should validate_presence_of(:visibility) } - - Platform::VISIBILITIES.each do |value| - it {should allow_value(value).for(:visibility)} - end - it {should_not allow_value('custom_status').for(:visibility)} - - it { should have_readonly_attribute(:name) } - it { should have_readonly_attribute(:distrib_type) } - it { should have_readonly_attribute(:parent_platform_id) } - it { should have_readonly_attribute(:platform_type) } - - it { should_not allow_mass_assignment_of(:repositories) } - it { should_not allow_mass_assignment_of(:products) } - it { should_not allow_mass_assignment_of(:members) } - it { should_not allow_mass_assignment_of(:parent) } - - it {should_not allow_value("How do you do...\nmy_platform").for(:name)} - - after(:all) do - Platform.delete_all - User.delete_all - clear_test_root + it 'ensures that folder of platform will be removed after destroy' do + platform = FactoryGirl.create(:platform) + FileUtils.mkdir_p platform.path + platform.destroy + Dir.exists?(platform.path).should be_false end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 98f1f1052..35ea72a33 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2,10 +2,36 @@ require 'spec_helper' describe Repository do + before { stub_symlink_methods } + + context 'ensures that validations and associations exist' do + before do + # Need for validate_uniqueness_of check + FactoryGirl.create(:repository) + end + + it { should belong_to(:platform) } + it { should have_many(:project_to_repositories).validate(true) } + it { should have_many(:projects).through(:project_to_repositories) } + + it { should validate_presence_of(:name) } + it { should validate_uniqueness_of(:name).case_insensitive.scoped_to(:platform_id) } + it { should allow_value('basic_repository-name-1234').for(:name) } + it { should_not allow_value('.!').for(:name) } + it { should_not allow_value('Main').for(:name) } + it { should_not allow_value("!!\nbang_bang\n!!").for(:name) } + it { should validate_presence_of(:description) } + + it { should have_readonly_attribute(:name) } + it { should have_readonly_attribute(:platform_id) } + + it { should_not allow_mass_assignment_of(:platform) } + it { should_not allow_mass_assignment_of(:platform_id) } + + end context 'when create with same owner that platform' do - before (:each) do - stub_symlink_methods + before do @platform = FactoryGirl.create(:platform) @params = {:name => 'tst_platform', :description => 'test platform'} end @@ -16,39 +42,31 @@ describe Repository do end end - before(:all) do - stub_symlink_methods - Platform.delete_all - User.delete_all - Repository.delete_all - init_test_root - # Need for validate_uniqueness_of check - FactoryGirl.create(:repository) - end + context 'ensures that folder of repository will be removed after destroy' do + let(:arch) { FactoryGirl.create(:arch) } + let(:types) { ['SRPM', arch.name] } - it { should belong_to(:platform) } - it { should have_many(:project_to_repositories).validate(true) } - it { should have_many(:projects).through(:project_to_repositories) } + it "repository of main platform" do + FactoryGirl.create(:arch) + r = FactoryGirl.create(:repository) + paths = types. + map{ |type| "#{r.platform.path}/repository/#{type}/#{r.name}" }. + each{ |path| FileUtils.mkdir_p path } + r.destroy + paths.each{ |path| Dir.exists?(path).should be_false } + end - it { should validate_presence_of(:name) } - it { should validate_uniqueness_of(:name).case_insensitive.scoped_to(:platform_id) } - it { should validate_format_of(:name).with('basic_repository-name-1234') } - it { should validate_format_of(:name).not_with('.!') } - it { should validate_format_of(:name).not_with('Main') } - it { should validate_format_of(:name).not_with("!!\nbang_bang\n!!") } - it { should validate_presence_of(:description) } + it "repository of personal platform" do + FactoryGirl.create(:arch) + main_platform = FactoryGirl.create(:platform) + r = FactoryGirl.create(:personal_repository) + paths = types. + map{ |type| "#{r.platform.path}/repository/#{main_platform.name}/#{type}/#{r.name}" }. + each{ |path| FileUtils.mkdir_p path } + r.destroy + paths.each{ |path| Dir.exists?(path).should be_false } + end - it { should have_readonly_attribute(:name) } - it { should have_readonly_attribute(:platform_id) } - - it { should_not allow_mass_assignment_of(:platform) } - it { should_not allow_mass_assignment_of(:platform_id) } - - after(:all) do - Platform.delete_all - User.delete_all - Repository.delete_all - clear_test_root end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6fe491877..c233dd750 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -28,6 +28,8 @@ RSpec.configure do |config| config.filter_run_excluding :anonymous_access => !(APP_CONFIG['anonymous_access']) + config.before(:all) { init_test_root } + config.after(:all) { clear_test_root } end def set_session_for(user=nil) @@ -65,8 +67,6 @@ def stub_redis stub(Resque).redis { @redis_instance } end -init_test_root - def fill_project project %x(mkdir -p #{project.path} && cp -Rf #{Rails.root}/spec/tests.git/* #{project.path}) # maybe FIXME ? end