#794: merge master into branch
This commit is contained in:
commit
097ffacf61
2
Gemfile
2
Gemfile
|
@ -1,6 +1,6 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
gem 'rails', '3.2.9' #, :git => 'git://github.com/rails/rails.git'
|
||||
gem 'rails', '3.2.11' #, :git => 'git://github.com/rails/rails.git'
|
||||
|
||||
gem 'pg', '~> 0.14.0'
|
||||
# gem 'silent-postgres', :git => 'git://github.com/dolzenko/silent-postgres.git' #'~> 0.1.1'
|
||||
|
|
184
Gemfile.lock
184
Gemfile.lock
|
@ -25,12 +25,12 @@ GEM
|
|||
remote: http://rubygems.org/
|
||||
specs:
|
||||
RedCloth (4.2.9)
|
||||
actionmailer (3.2.9)
|
||||
actionpack (= 3.2.9)
|
||||
actionmailer (3.2.11)
|
||||
actionpack (= 3.2.11)
|
||||
mail (~> 2.4.4)
|
||||
actionpack (3.2.9)
|
||||
activemodel (= 3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
actionpack (3.2.11)
|
||||
activemodel (= 3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
|
@ -38,39 +38,41 @@ GEM
|
|||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.2.1)
|
||||
activemodel (3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
activemodel (3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.9)
|
||||
activemodel (= 3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
activerecord (3.2.11)
|
||||
activemodel (= 3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.9)
|
||||
activemodel (= 3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
activesupport (3.2.9)
|
||||
activeresource (3.2.11)
|
||||
activemodel (= 3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
activesupport (3.2.11)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
airbrake (3.1.2)
|
||||
activesupport
|
||||
airbrake (3.1.6)
|
||||
builder
|
||||
girl_friday
|
||||
ancestry (1.3.0)
|
||||
activerecord (>= 2.3.14)
|
||||
arel (3.0.2)
|
||||
attr_encrypted (1.2.1)
|
||||
encryptor (>= 1.1.1)
|
||||
bcrypt-ruby (3.0.1)
|
||||
blankslate (2.1.2.4)
|
||||
blankslate (3.1.2)
|
||||
bluepill (0.0.60)
|
||||
activesupport (>= 3.0.0)
|
||||
daemons (~> 1.1.4, <= 1.1.6)
|
||||
i18n (>= 0.5.0)
|
||||
state_machine (~> 1.1.0)
|
||||
bourne (1.1.2)
|
||||
mocha (= 0.10.5)
|
||||
builder (3.0.4)
|
||||
cancan (1.6.7)
|
||||
cape (1.4.0)
|
||||
capistrano (2.12.0)
|
||||
cape (1.6.0)
|
||||
capistrano (2.14.1)
|
||||
highline
|
||||
net-scp (>= 1.0.0)
|
||||
net-sftp (>= 2.0.0)
|
||||
|
@ -79,22 +81,26 @@ GEM
|
|||
capistrano_colors (0.5.5)
|
||||
charlock_holmes (0.6.9)
|
||||
chronic (0.6.7)
|
||||
chunky_png (1.2.6)
|
||||
cocaine (0.2.1)
|
||||
chunky_png (1.2.7)
|
||||
climate_control (0.0.3)
|
||||
activesupport (>= 3.0)
|
||||
cocaine (0.5.1)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coffee-rails (3.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (~> 3.2.0)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.3.3)
|
||||
coffee-script-source (1.4.0)
|
||||
compass (0.12.2)
|
||||
chunky_png (~> 1.2)
|
||||
fssm (>= 0.2.7)
|
||||
sass (~> 3.1)
|
||||
compass-rails (1.0.3)
|
||||
compass (>= 0.12.2, < 0.14)
|
||||
creole (0.4.2)
|
||||
connection_pool (1.0.0)
|
||||
creole (0.5.0)
|
||||
daemons (1.1.6)
|
||||
devise (2.1.2)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
|
@ -107,7 +113,7 @@ GEM
|
|||
encryptor (1.1.3)
|
||||
erubis (2.7.0)
|
||||
escape_utils (0.2.4)
|
||||
eventmachine (0.12.10)
|
||||
eventmachine (1.0.0)
|
||||
execjs (1.4.0)
|
||||
multi_json (~> 1.0)
|
||||
expression_parser (0.9.0)
|
||||
|
@ -118,14 +124,17 @@ GEM
|
|||
railties (>= 3.0.0)
|
||||
ffi (1.0.11)
|
||||
fssm (0.2.9)
|
||||
girl_friday (0.11.2)
|
||||
connection_pool (~> 1.0)
|
||||
rubinius-actor
|
||||
github-linguist (2.2.1)
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.3)
|
||||
mime-types (~> 1.18)
|
||||
pygments.rb (>= 0.2.13)
|
||||
github-markdown (0.5.0)
|
||||
github-markup (0.7.4)
|
||||
gollum (2.1.3)
|
||||
github-markdown (0.5.3)
|
||||
github-markup (0.7.5)
|
||||
gollum (2.1.10)
|
||||
github-markdown
|
||||
github-markup (>= 0.7.0, < 1.0.0)
|
||||
grit (~> 2.5.0)
|
||||
|
@ -138,24 +147,24 @@ GEM
|
|||
stringex (~> 1.4.0)
|
||||
useragent (~> 0.4.9)
|
||||
haml (3.1.7)
|
||||
haml-rails (0.3.4)
|
||||
actionpack (~> 3.0)
|
||||
activesupport (~> 3.0)
|
||||
haml (~> 3.0)
|
||||
railties (~> 3.0)
|
||||
haml-rails (0.3.5)
|
||||
actionpack (>= 3.1, < 4.1)
|
||||
activesupport (>= 3.1, < 4.1)
|
||||
haml (~> 3.1)
|
||||
railties (>= 3.1, < 4.1)
|
||||
hashie (1.2.0)
|
||||
highline (1.6.13)
|
||||
highline (1.6.15)
|
||||
hike (1.2.1)
|
||||
hirb (0.7.0)
|
||||
i18n (0.6.1)
|
||||
jbuilder (0.8.2)
|
||||
jbuilder (0.8.3)
|
||||
activesupport (>= 3.0.0)
|
||||
journey (1.0.4)
|
||||
jquery-rails (2.0.2)
|
||||
railties (>= 3.2.0, < 5.0)
|
||||
jquery-rails (2.0.3)
|
||||
railties (>= 3.1.0, < 5.0)
|
||||
thor (~> 0.14)
|
||||
json (1.7.5)
|
||||
kgio (2.7.4)
|
||||
json (1.7.6)
|
||||
kgio (2.7.3)
|
||||
libv8 (3.3.10.4)
|
||||
macaddr (1.6.1)
|
||||
systemu (~> 2.5.0)
|
||||
|
@ -163,18 +172,21 @@ GEM
|
|||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mailcatcher (0.5.8)
|
||||
mailcatcher (0.5.10)
|
||||
activesupport (~> 3.0)
|
||||
eventmachine (~> 0.12)
|
||||
eventmachine (~> 1.0.0)
|
||||
haml (~> 3.1)
|
||||
mail (~> 2.3)
|
||||
sinatra (~> 1.2)
|
||||
skinny (~> 0.2, >= 0.2.1)
|
||||
skinny (~> 0.2.3)
|
||||
sqlite3 (~> 1.3)
|
||||
thin (~> 1.2)
|
||||
thin (~> 1.5.0)
|
||||
meta-tags (1.2.6)
|
||||
actionpack
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.19)
|
||||
mocha (0.10.5)
|
||||
metaclass (~> 0.0.1)
|
||||
mock_redis (0.6.2)
|
||||
multi_json (1.5.0)
|
||||
mustache (0.99.4)
|
||||
|
@ -182,12 +194,12 @@ GEM
|
|||
net-ssh (>= 1.99.1)
|
||||
net-sftp (2.0.5)
|
||||
net-ssh (>= 2.0.9)
|
||||
net-ssh (2.5.2)
|
||||
net-ssh (2.6.3)
|
||||
net-ssh-gateway (1.1.0)
|
||||
net-ssh (>= 1.99.1)
|
||||
newrelic_rpm (3.4.1)
|
||||
nokogiri (1.5.5)
|
||||
omniauth (1.1.0)
|
||||
newrelic_rpm (3.4.2.1)
|
||||
nokogiri (1.5.6)
|
||||
omniauth (1.1.1)
|
||||
hashie (~> 1.2)
|
||||
rack
|
||||
omniauth-openid (1.0.1)
|
||||
|
@ -204,18 +216,18 @@ GEM
|
|||
rails (~> 3.0)
|
||||
redis
|
||||
resque
|
||||
pg (0.14.0)
|
||||
pg (0.14.1)
|
||||
polyglot (0.3.3)
|
||||
posix-spawn (0.3.6)
|
||||
pygments.rb (0.2.13)
|
||||
rubypython (~> 0.5.3)
|
||||
rack (1.4.1)
|
||||
rack (1.4.4)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-openid (1.3.1)
|
||||
rack (>= 1.1.0)
|
||||
ruby-openid (>= 2.1.8)
|
||||
rack-protection (1.2.0)
|
||||
rack-protection (1.3.2)
|
||||
rack
|
||||
rack-ssl (1.3.2)
|
||||
rack
|
||||
|
@ -223,25 +235,25 @@ GEM
|
|||
rack (>= 1.0)
|
||||
rack-throttle (0.3.0)
|
||||
rack (>= 1.0.0)
|
||||
rails (3.2.9)
|
||||
actionmailer (= 3.2.9)
|
||||
actionpack (= 3.2.9)
|
||||
activerecord (= 3.2.9)
|
||||
activeresource (= 3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
rails (3.2.11)
|
||||
actionmailer (= 3.2.11)
|
||||
actionpack (= 3.2.11)
|
||||
activerecord (= 3.2.11)
|
||||
activeresource (= 3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.9)
|
||||
railties (= 3.2.11)
|
||||
rails-backbone (0.7.2)
|
||||
coffee-script (~> 2.2.0)
|
||||
ejs (~> 1.0.0)
|
||||
railties (>= 3.1.0)
|
||||
rails3-generators (0.17.4)
|
||||
rails3-generators (1.0.0)
|
||||
railties (>= 3.0.0)
|
||||
rails3-jquery-autocomplete (1.0.7)
|
||||
rails3-jquery-autocomplete (1.0.10)
|
||||
rails (~> 3.0)
|
||||
railties (3.2.9)
|
||||
actionpack (= 3.2.9)
|
||||
activesupport (= 3.2.9)
|
||||
railties (3.2.11)
|
||||
actionpack (= 3.2.11)
|
||||
activesupport (= 3.2.11)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
|
@ -252,7 +264,7 @@ GEM
|
|||
rdoc (3.12)
|
||||
json (~> 1.4)
|
||||
redcarpet (2.1.1)
|
||||
redis (3.0.1)
|
||||
redis (3.0.2)
|
||||
redis-namespace (1.2.1)
|
||||
redis (~> 3.0.0)
|
||||
redisk (0.2.2)
|
||||
|
@ -277,59 +289,63 @@ GEM
|
|||
rspec-expectations (~> 2.11.0)
|
||||
rspec-mocks (~> 2.11.0)
|
||||
rspec-core (2.11.1)
|
||||
rspec-expectations (2.11.2)
|
||||
rspec-expectations (2.11.3)
|
||||
diff-lcs (~> 1.1.3)
|
||||
rspec-mocks (2.11.2)
|
||||
rspec-rails (2.11.0)
|
||||
rspec-mocks (2.11.3)
|
||||
rspec-rails (2.11.4)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec (~> 2.11.0)
|
||||
rubinius-actor (0.0.2)
|
||||
rubinius-core-api
|
||||
rubinius-core-api (0.0.1)
|
||||
ruby-haml-js (0.0.3)
|
||||
execjs
|
||||
sprockets (>= 2.0.0)
|
||||
ruby-openid (2.2.0)
|
||||
ruby-openid (2.2.2)
|
||||
rubypython (0.5.3)
|
||||
blankslate (>= 2.1.2.3)
|
||||
ffi (~> 1.0.7)
|
||||
russian (0.6.0)
|
||||
i18n (>= 0.5.0)
|
||||
rvm-capistrano (1.2.5)
|
||||
rvm-capistrano (1.2.7)
|
||||
capistrano (>= 2.0.0)
|
||||
sanitize (2.0.3)
|
||||
nokogiri (>= 1.4.4, < 1.6)
|
||||
sass (3.2.0)
|
||||
sass-rails (3.2.5)
|
||||
sass (3.2.5)
|
||||
sass-rails (3.2.6)
|
||||
railties (~> 3.2.0)
|
||||
sass (>= 3.1.10)
|
||||
tilt (~> 1.3)
|
||||
shotgun (0.9)
|
||||
rack (>= 1.0)
|
||||
shoulda (3.1.1)
|
||||
shoulda-context (~> 1.0)
|
||||
shoulda-matchers (~> 1.2)
|
||||
shoulda-context (1.0.0)
|
||||
shoulda-matchers (1.2.0)
|
||||
shoulda (3.3.2)
|
||||
shoulda-context (~> 1.0.1)
|
||||
shoulda-matchers (~> 1.4.1)
|
||||
shoulda-context (1.0.2)
|
||||
shoulda-matchers (1.4.2)
|
||||
activesupport (>= 3.0.0)
|
||||
sinatra (1.3.2)
|
||||
bourne (~> 1.1.2)
|
||||
sinatra (1.3.3)
|
||||
rack (~> 1.3, >= 1.3.6)
|
||||
rack-protection (~> 1.2)
|
||||
tilt (~> 1.3, >= 1.3.3)
|
||||
skinny (0.2.1)
|
||||
eventmachine (~> 0.12)
|
||||
thin (~> 1.2)
|
||||
skinny (0.2.3)
|
||||
eventmachine (~> 1.0.0)
|
||||
thin (~> 1.5.0)
|
||||
sprockets (2.2.2)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sqlite3 (1.3.6)
|
||||
sqlite3 (1.3.7)
|
||||
state_machine (1.1.2)
|
||||
stringex (1.4.0)
|
||||
systemu (2.5.2)
|
||||
therubyracer (0.10.2)
|
||||
libv8 (~> 3.3.10)
|
||||
thin (1.4.1)
|
||||
thin (1.5.0)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 0.12.6)
|
||||
rack (>= 1.0.0)
|
||||
|
@ -346,8 +362,8 @@ GEM
|
|||
kgio (~> 2.6)
|
||||
rack
|
||||
raindrops (~> 0.7)
|
||||
useragent (0.4.10)
|
||||
uuid (2.3.5)
|
||||
useragent (0.4.16)
|
||||
uuid (2.3.6)
|
||||
macaddr (~> 1.0)
|
||||
vegas (0.1.11)
|
||||
rack (>= 1.0.0)
|
||||
|
@ -359,7 +375,7 @@ GEM
|
|||
wikicloth (0.8.0)
|
||||
builder
|
||||
expression_parser
|
||||
will_paginate (3.0.3)
|
||||
will_paginate (3.0.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -400,7 +416,7 @@ DEPENDENCIES
|
|||
perform_later (~> 1.3.0)
|
||||
pg (~> 0.14.0)
|
||||
rack-throttle
|
||||
rails (= 3.2.9)
|
||||
rails (= 3.2.11)
|
||||
rails-backbone (~> 0.7.2)
|
||||
rails3-generators
|
||||
rails3-jquery-autocomplete (~> 1.0.7)
|
||||
|
|
|
@ -2,23 +2,34 @@
|
|||
class Admin::UsersController < Admin::BaseController
|
||||
include AvatarHelper
|
||||
prepend_before_filter :find_user
|
||||
load_and_authorize_resource :collection => [:system, :list]
|
||||
|
||||
def index
|
||||
@filter = params[:filter] || 'all'
|
||||
end
|
||||
|
||||
def system
|
||||
@users, @filter = @users.system, 'system'
|
||||
render :index
|
||||
end
|
||||
|
||||
def new
|
||||
@user.role = 'system' if params[:system] == 'true'
|
||||
end
|
||||
|
||||
def create
|
||||
@user.role = params[:role]
|
||||
@user.email, @user.password = "#{@user.uname}@rosalinux.ru", SecureRandom.base64 if @user.system?
|
||||
@user.confirmed_at = Time.now.utc
|
||||
if (@user.save rescue false)
|
||||
flash[:notice] = t('flash.user.saved')
|
||||
redirect_to admin_users_path
|
||||
flash[:warning] = @user.authentication_token
|
||||
redirect_to(@user.system? ? system_admin_users_path : admin_users_path)
|
||||
else
|
||||
flash[:error] = t('flash.user.save_error')
|
||||
flash[:warning] = @user.errors.full_messages.join('. ')
|
||||
@system = @user.system?
|
||||
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
|
@ -42,11 +53,15 @@ class Admin::UsersController < Admin::BaseController
|
|||
def destroy
|
||||
@user.destroy
|
||||
flash[:notice] = t("flash.user.destroyed")
|
||||
redirect_to admin_users_path
|
||||
redirect_to(@user.system? ? system_admin_users_path : admin_users_path)
|
||||
end
|
||||
|
||||
def list
|
||||
colName = ['users.name', 'users.uname', 'users.email']
|
||||
if params[:system] != 'true'
|
||||
colName, @users = ['users.name', 'users.uname', 'users.email'], @users.opened
|
||||
else
|
||||
colName, @users, @system_list = ['users.uname'], @users.system, true
|
||||
end
|
||||
sort_col = params[:iSortCol_0] || 0
|
||||
sort_dir = params[:sSortDir_0]=="asc" ? 'asc' : 'desc'
|
||||
order = "#{colName[sort_col.to_i]} #{sort_dir}"
|
||||
|
@ -63,6 +78,13 @@ class Admin::UsersController < Admin::BaseController
|
|||
render :partial => 'users_ajax', :layout => false
|
||||
end
|
||||
|
||||
def reset_auth_token
|
||||
@user.reset_authentication_token!
|
||||
flash[:notice] = t("flash.user.reset_auth_token")
|
||||
flash[:warning] = @user.authentication_token
|
||||
redirect_to system_admin_users_path
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def find_user
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class Api::V1::UsersController < Api::V1::BaseController
|
||||
|
||||
|
||||
before_filter :authenticate_user!
|
||||
skip_before_filter :authenticate_user!, :only => [:show] if APP_CONFIG['anonymous_access']
|
||||
load_and_authorize_resource :user, :only => :show
|
||||
before_filter :set_current_user, :except => :show
|
||||
|
||||
def show
|
||||
@user = User.opened.find params[:id] # dont show system users
|
||||
end
|
||||
|
||||
def show_current_user
|
||||
|
@ -45,4 +46,4 @@ class Api::V1::UsersController < Api::V1::BaseController
|
|||
@user = current_user
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ class Users::BaseController < ApplicationController
|
|||
|
||||
def find_user
|
||||
if user_id = params[:uname] || params[:user_id] || params[:id]
|
||||
@user = User.find_by_insensitive_uname! user_id
|
||||
@user = User.opened.find_by_insensitive_uname! user_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
|
|||
|
||||
when 'Issue'
|
||||
record.collect_recipients.each do |recipient|
|
||||
next if record.user_id == recipient.id
|
||||
UserMailer.new_issue_notification(record, recipient).deliver if recipient.notifier.can_notify && recipient.notifier.new_issue
|
||||
ActivityFeed.create(
|
||||
:user => recipient,
|
||||
|
|
|
@ -39,6 +39,10 @@ class BuildList < ActiveRecord::Base
|
|||
}
|
||||
}
|
||||
|
||||
validate lambda {
|
||||
errors.add(:save_to_repository, I18n.t('flash.build_list.wrong_project')) unless save_to_repository.projects.exists?(project_id)
|
||||
}
|
||||
|
||||
attr_accessible :include_repos, :auto_publish, :build_for_platform_id, :commit_hash,
|
||||
:arch_id, :project_id, :save_to_repository_id, :update_type,
|
||||
:save_to_platform_id, :new_core, :project_version
|
||||
|
@ -147,8 +151,6 @@ class BuildList < ActiveRecord::Base
|
|||
after_transition :on => :published, :do => [:set_version_and_tag, :actualize_packages]
|
||||
after_transition :on => :cancel, :do => [:cancel_job],
|
||||
:if => lambda { |build_list| build_list.new_core? }
|
||||
after_transition :on => :publish, :do => [:publish_container],
|
||||
:if => lambda { |build_list| build_list.new_core? }
|
||||
|
||||
after_transition :on => [:published, :fail_publish, :build_error], :do => :notify_users
|
||||
after_transition :on => :build_success, :do => :notify_users,
|
||||
|
@ -267,48 +269,13 @@ class BuildList < ActiveRecord::Base
|
|||
can_publish? and not save_to_repository.publish_without_qa
|
||||
end
|
||||
|
||||
def publish_container
|
||||
type = build_for_platform.distrib_type
|
||||
archive = results.select{ |r| r['file_name'] =~ /.*\.tar\.gz$/}[0]
|
||||
|
||||
platform_path = "#{save_to_platform.path}/repository"
|
||||
if save_to_platform.personal?
|
||||
platform_path << '/'
|
||||
platform_path << build_for_platform.name
|
||||
Dir.mkdir(platform_path) unless File.exists?(platform_path)
|
||||
end
|
||||
|
||||
packages = last_published.includes(:packages).limit(5).map{ |bl| bl.packages }.flatten
|
||||
sources = packages.map{ |p| p.fullname if p.package_type == 'source' }.compact
|
||||
binaries = packages.map{ |p| p.fullname if p.package_type == 'binary' }.compact
|
||||
|
||||
Resque.push(
|
||||
"publish_build_list_container_#{type}_worker",
|
||||
'class' => "AbfWorker::PublishBuildListContainer#{type.capitalize}Worker",
|
||||
'args' => [{
|
||||
:id => id,
|
||||
:arch => arch.name,
|
||||
:distrib_type => type,
|
||||
:container_sha1 => archive['sha1'],
|
||||
:packages => { :sources => sources, :binaries => binaries },
|
||||
:platform => {
|
||||
:platform_path => platform_path,
|
||||
:released => save_to_platform.released
|
||||
},
|
||||
:repository => {
|
||||
:name => save_to_repository.name,
|
||||
:id => save_to_repository.id
|
||||
},
|
||||
:type => :publish,
|
||||
:time_living => 2400 # 40 min
|
||||
}]
|
||||
)
|
||||
end
|
||||
|
||||
def add_to_queue
|
||||
if new_core?
|
||||
# TODO: Investigate: why 2 tasks will be created without checking @state
|
||||
add_job_to_abf_worker_queue unless @status
|
||||
unless @status
|
||||
add_job_to_abf_worker_queue
|
||||
update_column(:bs_id, id)
|
||||
end
|
||||
@status ||= BUILD_PENDING
|
||||
else
|
||||
# XML-RPC params:
|
||||
|
@ -416,8 +383,25 @@ class BuildList < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def last_published
|
||||
BuildList.where(:project_id => self.project_id,
|
||||
:save_to_repository_id => self.save_to_repository_id)
|
||||
.for_platform(self.build_for_platform_id)
|
||||
.scoped_to_arch(self.arch_id)
|
||||
.for_status(BUILD_PUBLISHED)
|
||||
.recent
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def abf_worker_priority
|
||||
mass_build_id ? '' : 'default'
|
||||
end
|
||||
|
||||
def abf_worker_base_queue
|
||||
'rpm_worker'
|
||||
end
|
||||
|
||||
def abf_worker_args
|
||||
include_repos_hash = {}.tap do |h|
|
||||
include_repos.each do |r|
|
||||
|
@ -493,12 +477,4 @@ class BuildList < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def last_published
|
||||
BuildList.where(:project_id => self.project_id,
|
||||
:save_to_repository_id => self.save_to_repository_id)
|
||||
.for_platform(self.build_for_platform_id)
|
||||
.scoped_to_arch(self.arch_id)
|
||||
.for_status(BUILD_PUBLISHED)
|
||||
.recent
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,12 +5,13 @@ class BuildList::Package < ActiveRecord::Base
|
|||
belongs_to :project
|
||||
belongs_to :platform
|
||||
|
||||
attr_accessible :fullname, :name, :release, :version
|
||||
attr_accessible :fullname, :name, :release, :version, :sha1
|
||||
|
||||
validates :build_list_id, :project_id, :platform_id, :fullname,
|
||||
:package_type, :name, :release, :version,
|
||||
:presence => true
|
||||
validates :package_type, :inclusion => PACKAGE_TYPES
|
||||
validates :sha1, :presence => true, :if => Proc.new { |p| p.build_list.new_core? }
|
||||
|
||||
default_scope order('lower(name) ASC, length(name) ASC')
|
||||
|
||||
|
|
|
@ -47,6 +47,10 @@ class Group < Avatar
|
|||
Relation.remove_member(member, self)
|
||||
end
|
||||
|
||||
def system?
|
||||
false
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def add_owner_to_members
|
||||
|
|
|
@ -47,10 +47,10 @@ class MassBuild < ActiveRecord::Base
|
|||
list = (missed_projects_list || '') << "#{name}\n"
|
||||
update_column :missed_projects_list, list
|
||||
end
|
||||
sleep 1
|
||||
sleep 1 unless new_core
|
||||
end
|
||||
end
|
||||
later :build_all, :loner => true, :queue => :clone_build
|
||||
later :build_all, :queue => :clone_build
|
||||
|
||||
def generate_failed_builds_list
|
||||
report = ""
|
||||
|
|
|
@ -129,6 +129,14 @@ class ProductBuildList < ActiveRecord::Base
|
|||
|
||||
protected
|
||||
|
||||
def abf_worker_priority
|
||||
''
|
||||
end
|
||||
|
||||
def abf_worker_base_queue
|
||||
'iso_worker'
|
||||
end
|
||||
|
||||
def abf_worker_args
|
||||
file_name = "#{project.owner.uname}-#{project.name}-#{commit_hash}"
|
||||
opts = {:host => ActionMailer::Base.default_url_options[:host]}
|
||||
|
|
|
@ -137,12 +137,14 @@ class Project < ActiveRecord::Base
|
|||
main_rep_id = platform.repositories.find_by_name('main').try(:id)
|
||||
build_reps_ids = [main_rep_id, repository_id].compact.uniq
|
||||
|
||||
build_lists.create do |bl|
|
||||
project_version = repo.commits("#{platform.name}").try(:first).try(:id) ?
|
||||
"latest_#{platform.name}" : "latest_master"
|
||||
build_list = build_lists.build do |bl|
|
||||
bl.save_to_platform = platform
|
||||
bl.build_for_platform = platform
|
||||
bl.update_type = 'newpackage'
|
||||
bl.arch = arch
|
||||
bl.project_version = "latest_#{platform.name}"
|
||||
bl.project_version = project_version
|
||||
bl.user = user
|
||||
bl.auto_publish = auto_publish
|
||||
bl.include_repos = build_reps_ids
|
||||
|
@ -151,6 +153,7 @@ class Project < ActiveRecord::Base
|
|||
bl.save_to_repository_id = repository_id
|
||||
bl.new_core = new_core
|
||||
end
|
||||
build_list.save
|
||||
end
|
||||
|
||||
def fork(new_owner)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class User < Avatar
|
||||
ROLES = ['', 'admin', 'banned', 'tester']
|
||||
EXTENDED_ROLES = ROLES | ['system']
|
||||
LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']]
|
||||
LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
|
||||
|
||||
|
@ -31,7 +32,7 @@ class User < Avatar
|
|||
|
||||
validates :uname, :presence => true, :uniqueness => {:case_sensitive => false}, :format => {:with => /\A[a-z0-9_]+\z/}, :reserved_name => true
|
||||
validate { errors.add(:uname, :taken) if Group.by_uname(uname).present? }
|
||||
validates :role, :inclusion => {:in => ROLES}, :allow_blank => true
|
||||
validates :role, :inclusion => {:in => EXTENDED_ROLES}, :allow_blank => true
|
||||
validates :language, :inclusion => {:in => LANGUAGES}, :allow_blank => true
|
||||
|
||||
attr_accessible :email, :password, :password_confirmation, :current_password, :remember_me, :login, :name, :uname, :language,
|
||||
|
@ -39,17 +40,17 @@ class User < Avatar
|
|||
attr_readonly :uname
|
||||
attr_accessor :login
|
||||
|
||||
scope :opened, where('1=1')
|
||||
scope :banned, where(:role => 'banned')
|
||||
scope :admin, where(:role => 'admin')
|
||||
scope :tester, where(:role => 'tester')
|
||||
scope :opened, where('users.role != \'system\' OR users.role IS NULL')
|
||||
scope :real, where(:role => ['', nil])
|
||||
EXTENDED_ROLES.select {|type| type.present?}.each do |type|
|
||||
scope type.to_sym, where(:role => type)
|
||||
end
|
||||
|
||||
scope :member_of_project, lambda {|item|
|
||||
where "#{table_name}.id IN (?)", item.members.map(&:id).uniq
|
||||
}
|
||||
|
||||
after_create lambda { self.create_notifier }
|
||||
after_create lambda { self.create_notifier unless self.system? }
|
||||
before_create :ensure_authentication_token
|
||||
|
||||
include Modules::Models::PersonalRepository
|
||||
|
@ -71,6 +72,10 @@ class User < Avatar
|
|||
role == 'tester'
|
||||
end
|
||||
|
||||
def system?
|
||||
role == 'system'
|
||||
end
|
||||
|
||||
def access_locked?
|
||||
role == 'banned'
|
||||
end
|
||||
|
@ -87,7 +92,9 @@ class User < Avatar
|
|||
def find_for_database_authentication(warden_conditions)
|
||||
conditions = warden_conditions.dup
|
||||
login = conditions.delete(:login)
|
||||
where(conditions).where(["lower(uname) = :value OR lower(email) = :value", { :value => login.downcase }]).first
|
||||
where(conditions)
|
||||
.where(["lower(uname) = :value OR lower(email) = :value OR authentication_token = :orig_value",
|
||||
{ :value => login.downcase, :orig_value => login }]).first
|
||||
end
|
||||
|
||||
def new_with_session(params, session)
|
||||
|
@ -103,6 +110,11 @@ class User < Avatar
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def auth_by_token_or_login_pass(user, pass)
|
||||
u = User.find_for_database_authentication(:login => user)
|
||||
u if u && !u.access_locked? && (u.authentication_token == user || u.valid_password?(pass))
|
||||
end
|
||||
end
|
||||
|
||||
# def update_with_password(params={})
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
- content_for :sidebar do
|
||||
-if @filter == 'system'
|
||||
.bordered
|
||||
= link_to t("layout.users.list_header"), admin_users_path, :class => 'button'
|
||||
.bordered
|
||||
- if can? :create, User.new
|
||||
= link_to t("layout.users.new"), new_admin_user_path, :class => 'button'
|
||||
= link_to t("layout.users.new"), new_admin_user_path(:system => @filter == 'system'), :class => 'button'
|
||||
%h3= t("layout.users.filter_header")
|
||||
%table
|
||||
- t('layout.users.users_filter').each_key do |base|
|
||||
-if @filter != 'system'
|
||||
- t('layout.users.users_filter').each_key do |base|
|
||||
%tr
|
||||
%td.width18=radio_button_tag :myradio, base, @filter.to_sym == base, {:id => 'users_filter', :class => 'niceRadio', :name => 'filter'}
|
||||
%td.width135=t("layout.users.users_filter.#{base}")
|
||||
-else
|
||||
%tr
|
||||
%td.width18=radio_button_tag :myradio, base, @filter.to_sym == base, {:id => 'users_filter', :class => 'niceRadio', :name => 'filter'}
|
||||
%td.width135=t("layout.users.users_filter.#{base}")
|
||||
%td.width18=radio_button_tag :myradio, 'system', true, {:id => 'users_filter', :class => 'niceRadio', :name => 'filter'}
|
||||
%td.width135=t("layout.users.system")
|
||||
.both
|
||||
-if @filter != 'system'
|
||||
.bordered
|
||||
= link_to t("layout.users.system"), system_admin_users_path, :class => 'button'
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
users = @users.map do |user|
|
||||
link_block = [
|
||||
(link_to t('layout.show'), user if can? :read, user),
|
||||
(link_to t('layout.edit'), edit_admin_user_path(user) if can? :edit, user),
|
||||
(link_to t('layout.show'), user if can?(:read, user) && !@system_list),
|
||||
(link_to t('layout.edit'), edit_admin_user_path(user) if can?(:edit, user) && !@system_list),
|
||||
(link_to t('layout.users.reset_token'), reset_auth_token_admin_user_path(user), :method => :put, :confirm => t('layout.users.confirm_reset_token') if can?(:edit, user) && @system_list),
|
||||
(link_to t('layout.delete'), admin_user_path(user), :method => :delete, :confirm => t('layout.users.confirm_delete') if can? :destroy, user)
|
||||
].compact.join(' | ').html_safe
|
||||
|
||||
[
|
||||
user.name,
|
||||
user.uname,
|
||||
user.email,
|
||||
content_tag(:span, user.role, :style => user.access_locked? ? 'background: #FEDEDE' : ''),
|
||||
link_block
|
||||
]
|
||||
if !@system_list
|
||||
[
|
||||
user.name,
|
||||
user.uname,
|
||||
user.email,
|
||||
content_tag(:span, user.role, :style => user.access_locked? ? 'background: #FEDEDE' : ''),
|
||||
link_block
|
||||
]
|
||||
else
|
||||
[
|
||||
user.uname,
|
||||
link_block
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
%h3.fix= title t("layout.users.list_header")
|
||||
|
||||
- columns = [{:type => 'html'}, {:type => 'html'}, {:type => 'html'}, {:type => 'html', :sortable => false, :searchable => false}, {:type => nil, :sortable => false, :searchable => false, :class => 'buttons'}]
|
||||
%h3.fix= title t("layout.users.#{@filter == 'system' ? 'system' : 'list_header'}")
|
||||
-if @filter == 'system'
|
||||
- columns = [{:type => 'html'}, {:type => nil, :sortable => false, :searchable => false, :class => 'buttons'}]
|
||||
-else
|
||||
- columns = [{:type => 'html'}, {:type => 'html'}, {:type => 'html'}, {:type => 'html', :sortable => false, :searchable => false}, {:type => nil, :sortable => false, :searchable => false, :class => 'buttons'}]
|
||||
= raw datatable(columns, {:sort_by => "[0, 'asc']", :processing => t("layout.processing"), :search_label => t("layout.search.header"),
|
||||
:pagination_labels => {:previous => t("datatables.previous_label"), :next => t("datatables.next_label")},
|
||||
:empty_label => t("datatables.empty_label"),
|
||||
|
@ -9,16 +11,19 @@
|
|||
:filtered_label => t("datatables.filtered_label"),
|
||||
:table_dom_id => 'datatable',
|
||||
:auto_width => 'false',
|
||||
:ajax_source => "#{url_for :controller => 'admin/users', :action => :list}",
|
||||
:ajax_source => "#{url_for :controller => 'admin/users', :action => :list, :system => (@filter == 'system')}",
|
||||
:additional_data => {:filter => "' + $('#users_filter[type=\"radio\"]:checked').val() + '"} })
|
||||
|
||||
%table#datatable.tablesorter.list-users{:cellspacing => 0, :cellpadding => 0}
|
||||
%thead
|
||||
%tr
|
||||
%th.th1= t("activerecord.attributes.user.name")
|
||||
%th.th2= t("activerecord.attributes.user.uname")
|
||||
%th.th3= t("activerecord.attributes.user.email")
|
||||
%th.th4= t("activerecord.attributes.user.role")
|
||||
-if @filter == 'system'
|
||||
%th.th2= t("activerecord.attributes.user.uname")
|
||||
-else
|
||||
%th.th1= t("activerecord.attributes.user.name")
|
||||
%th.th2= t("activerecord.attributes.user.uname")
|
||||
%th.th3= t("activerecord.attributes.user.email")
|
||||
%th.th4= t("activerecord.attributes.user.role")
|
||||
%th.last
|
||||
%tbody
|
||||
%br
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
.block
|
||||
.content
|
||||
%h2.title= title t("layout.users.new_header")
|
||||
%h2.title= title t("layout.users.new_#{@user.system? ? 'system_' : ''}header")
|
||||
.inner
|
||||
= form_for @user, :url => admin_users_path, :html => {:class => :form} do |f|
|
||||
= render "users/base/form", :f => f
|
||||
|
||||
-if @user.system?
|
||||
=hidden_field_tag :role, 'system'
|
||||
.leftlist= f.label :uname, t("activerecord.attributes.user.uname")
|
||||
.rightlist= f.text_field :uname
|
||||
.leftlist
|
||||
\
|
||||
.rightlist= submit_tag t("layout.save"), :data => {:"disable-with" => t("layout.saving")}
|
||||
.both
|
||||
-else
|
||||
= render "users/base/form", :f => f
|
||||
- content_for :sidebar do
|
||||
.bordered.nopadding
|
||||
= render 'submenu'
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
.registration
|
||||
.remember
|
||||
.check
|
||||
%span#niceCheckbox1.niceCheck
|
||||
= f.check_box :remember_me
|
||||
%span#niceCheckbox1.niceCheck{:style => 'background-position: 0px -18px;'}
|
||||
= f.check_box :remember_me, :checked => true
|
||||
.text=t('devise.sessions.remember_me')
|
||||
.in=f.submit t('layout.devise.shared_links.sign_in'), :class => 'button', :id => 'btnLogin'
|
||||
%div{:style => "clear: both;"}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
-set_meta_tags :title => t('.title')
|
||||
|
||||
= hidden_field_tag :servertime, Time.now.utc.to_i
|
||||
%div.reloader
|
||||
= label_tag :autoreload do
|
||||
= check_box_tag :autoreload, true, true
|
||||
|
@ -46,7 +47,7 @@
|
|||
.replace("%d", formatNumber(minutes));
|
||||
}
|
||||
// TODO Very, very ugly method.
|
||||
var now = (new Date).getTime();
|
||||
var now = $('#servertime').val() * 1000;
|
||||
$("time.js-relative-date").each(function() {
|
||||
var time = parseIso8601($(this).attr('datetime')).getTime();
|
||||
$(this).text(strTimeBetween(time, now));
|
||||
|
|
|
@ -167,7 +167,10 @@
|
|||
%tbody
|
||||
- @build_list.packages.each do |package|
|
||||
%tr
|
||||
%td= package.fullname
|
||||
- if package.sha1.present?
|
||||
%td= link_to package.fullname, "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{package.sha1}"
|
||||
- else
|
||||
%td= package.fullname
|
||||
%td= package.name
|
||||
%td= package.version
|
||||
%td= package.release
|
||||
|
|
|
@ -14,7 +14,7 @@ en:
|
|||
We are glad that you have expressed interest in our ABF service!<br><br>
|
||||
Your registration confirmation will be sent to the e-mail address you have specified in the registration form.<br><br>
|
||||
We will be glad to get feedback and to answer your questions in our <a class='last' href="http://forum.rosalab.ru/viewforum.php?f=10">forum</a>.<br><br>
|
||||
You can get detailed documentation <a class='last' href="http://wiki.rosalab.ru/index.php/Сборочная_среда_ABF">here</a>.
|
||||
You can get detailed documentation <a class='last' href="http://wiki.rosalab.ru/en/index.php/ABF">here</a>.
|
||||
|
||||
want: I want to become ABF beta-tester!
|
||||
login_email: Login or email
|
||||
|
|
|
@ -148,6 +148,7 @@ en:
|
|||
wrong_platform: Only the primary platform can be selected for the main repository!
|
||||
wrong_build_for_platform: Type of platform in "build_for_platform" should be "main"
|
||||
wrong_repository: Repository to save package to must belongs to platform.
|
||||
wrong_project: Repository does not contain project.
|
||||
cannot_write: You can't build project to this repository.
|
||||
can_not_published: Build can only be published with status "Build complete"
|
||||
frozen_platform: In case of a repository for package storage with frozen platform allowed only bugfix and security updates
|
||||
|
|
|
@ -145,6 +145,7 @@ ru:
|
|||
wrong_platform: Для основного репозитория (main) может быть выбран только его же основная платформа!
|
||||
wrong_build_for_platform: Тип платформы "build_for_platform" должен быть "main"
|
||||
wrong_repository: Репозиторий для сохранения должен принадлежать платформе.
|
||||
wrong_project: Репозиторий не содержит проект.
|
||||
cannot_write: Вы не можете собирать пакет в этот репозиторий.
|
||||
can_not_published: Опубликовать сборку можно только со статусом "Собран"
|
||||
frozen_platform: В случае выбора репозитория для сохранения пакетов из замороженнной платформы разрешены только bugfix и security обновления
|
||||
|
|
|
@ -5,21 +5,26 @@ en:
|
|||
new: Create
|
||||
edit: Edit
|
||||
new_header: New user
|
||||
new_system_header: New system user
|
||||
edit_header: Edit
|
||||
list_header: Users
|
||||
groups: Groups
|
||||
show: User
|
||||
back_to_the_list: ⇐ List of users
|
||||
confirm_delete: Are you sure you want to remove this user?
|
||||
confirm_reset_token: Are you sure you want to reset token for this user?
|
||||
own_projects: My projects
|
||||
part_projects: Projects participation
|
||||
filter_header: Filter
|
||||
system: System accounts
|
||||
reset_token: Reset token
|
||||
|
||||
flash:
|
||||
user:
|
||||
saved: User saved successtully
|
||||
saved: User saved successfully
|
||||
save_error: Unable to save user data
|
||||
destroyed: User account deleted
|
||||
reset_auth_token: User token reseted successfully
|
||||
|
||||
activerecord:
|
||||
models:
|
||||
|
|
|
@ -5,21 +5,26 @@ ru:
|
|||
new: Создать
|
||||
edit: Редактировать
|
||||
new_header: Новый пользователь
|
||||
new_system_header: Новый служебный пользователь
|
||||
edit_header: Редактировать
|
||||
list_header: Пользователи
|
||||
groups: Группы
|
||||
show: Пользователь
|
||||
back_to_the_list: ⇐ К списку пользователей
|
||||
confirm_delete: Вы уверены, что хотите удалить этого пользователя?
|
||||
confirm_reset_token: Вы уверены, что хотите сбросить токен этого пользователя?
|
||||
own_projects: Мои проекты
|
||||
part_projects: Участвую в проектах
|
||||
filter_header: Фильтр
|
||||
system: Служебные учетки
|
||||
reset_token: Сбросить токен
|
||||
|
||||
flash:
|
||||
user:
|
||||
saved: Пользователь успешно сохранен
|
||||
save_error: Не удалось сохранить данные о пользователе
|
||||
destroyed: Учетная запись успешно удалена
|
||||
reset_auth_token: Для учетной записи изменен токен
|
||||
|
||||
activerecord:
|
||||
models:
|
||||
|
|
|
@ -16,9 +16,9 @@ Rosa::Application.routes.draw do
|
|||
resources :search, :only => [:index]
|
||||
resources :build_lists, :only => [:index, :create, :show] do
|
||||
member {
|
||||
get :publish
|
||||
get :reject_publish
|
||||
get :cancel
|
||||
put :publish
|
||||
put :reject_publish
|
||||
put :cancel
|
||||
}
|
||||
end
|
||||
resources :arches, :only => [:index]
|
||||
|
@ -96,7 +96,11 @@ Rosa::Application.routes.draw do
|
|||
|
||||
namespace :admin do
|
||||
resources :users do
|
||||
get :list, :on => :collection
|
||||
collection do
|
||||
get :list
|
||||
get :system
|
||||
end
|
||||
put :reset_auth_token, :on => :member
|
||||
end
|
||||
resources :register_requests, :only => [:index] do
|
||||
put :update, :on => :collection
|
||||
|
|
|
@ -22,3 +22,7 @@ end
|
|||
every 1.day, :at => '3:00 am' do
|
||||
rake "activity_feeds:clear", :output => 'log/activity_feeds.log'
|
||||
end
|
||||
|
||||
every 3.minute do
|
||||
runner 'AbfWorker::BuildListsPublishTaskManager.new.run', :output => 'log/task_manager.log'
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AbbSha1ToBuildListPackage < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :build_list_packages, :sha1, :string
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20121225103309) do
|
||||
ActiveRecord::Schema.define(:version => 20130110104600) do
|
||||
|
||||
create_table "activity_feeds", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
|
@ -94,6 +94,7 @@ ActiveRecord::Schema.define(:version => 20121225103309) do
|
|||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.boolean "actual", :default => false
|
||||
t.string "sha1"
|
||||
end
|
||||
|
||||
add_index "build_list_packages", ["actual", "platform_id"], :name => "index_build_list_packages_on_actual_and_platform_id"
|
||||
|
|
|
@ -5,7 +5,7 @@ ARCHES.each do |arch|
|
|||
end
|
||||
|
||||
user = User.new uname: 'rosa_system', email: 'rosa_system@rosalinux.ru', password: SecureRandom.base64
|
||||
user.confirmed_at = Time.now.utc; user.save
|
||||
user.confirmed_at, user.role = Time.now.utc, 'system'; user.save
|
||||
|
||||
user = User.new uname: 'iso_worker_1', email: 'iso_worker_1@rosalinux.ru', password: SecureRandom.base64
|
||||
user.confirmed_at = Time.now.utc; user.save
|
||||
user.confirmed_at, user.role = Time.now.utc, 'system'; user.save
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
module AbfWorker
|
||||
class BuildListsPublishTaskManager
|
||||
REDIS_MAIN_KEY = 'abf-worker::build-lists-publish-task-manager::'
|
||||
LOCKED_REP_AND_PLATFORMS = "#{REDIS_MAIN_KEY}locked-repositories-and-platforms"
|
||||
LOCKED_BUILD_LISTS = "#{REDIS_MAIN_KEY}locked-build-lists"
|
||||
|
||||
def initialize
|
||||
@redis = Resque.redis
|
||||
@workers_count = APP_CONFIG['abf_worker']['publish_workers_count']
|
||||
end
|
||||
|
||||
def run
|
||||
available_repos = BuildList.
|
||||
select('MIN(updated_at) as min_updated_at, save_to_repository_id, build_for_platform_id').
|
||||
where(:new_core => true, :status => BuildList::BUILD_PUBLISH).
|
||||
group(:save_to_repository_id, :build_for_platform_id).
|
||||
order(:min_updated_at).
|
||||
limit(@workers_count * 2) # because some repos may be locked
|
||||
|
||||
counter = 1
|
||||
|
||||
# looks like:
|
||||
# ['save_to_repository_id-build_for_platform_id', ...]
|
||||
locked_rep_and_pl = @redis.lrange(LOCKED_REP_AND_PLATFORMS, 0, -1)
|
||||
available_repos.each do |el|
|
||||
key = "#{el.save_to_repository_id}-#{el.build_for_platform_id}"
|
||||
next if locked_rep_and_pl.include?(key)
|
||||
break if counter > @workers_count
|
||||
if create_task(el.save_to_repository_id, el.build_for_platform_id)
|
||||
@redis.lpush(LOCKED_REP_AND_PLATFORMS, key)
|
||||
counter += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.unlock_build_list(build_list)
|
||||
Resque.redis.lrem(LOCKED_BUILD_LISTS, 0, build_list.id)
|
||||
end
|
||||
|
||||
def self.unlock_rep_and_platform(build_list)
|
||||
key = "#{build_list.save_to_repository_id}-#{build_list.build_for_platform_id}"
|
||||
Resque.redis.lrem(LOCKED_REP_AND_PLATFORMS, 0, key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_task(save_to_repository_id, build_for_platform_id)
|
||||
build_lists = BuildList.
|
||||
where(:new_core => true, :status => BuildList::BUILD_PUBLISH).
|
||||
where(:save_to_repository_id => save_to_repository_id).
|
||||
where(:build_for_platform_id => build_for_platform_id).
|
||||
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?
|
||||
|
||||
bl = build_lists.first
|
||||
return false unless bl
|
||||
|
||||
platform_path = "#{bl.save_to_platform.path}/repository"
|
||||
if bl.save_to_platform.personal?
|
||||
platform_path << '/' << bl.build_for_platform.name
|
||||
system "mkdir -p #{platform_path}"
|
||||
end
|
||||
worker_queue = bl.worker_queue_with_priority("publish_worker")
|
||||
worker_class = bl.worker_queue_class("AbfWorker::PublishWorker")
|
||||
|
||||
options = {
|
||||
:id => bl.id,
|
||||
:arch => bl.arch.name,
|
||||
:distrib_type => bl.build_for_platform.distrib_type,
|
||||
:platform => {
|
||||
:platform_path => platform_path,
|
||||
:released => bl.save_to_platform.released
|
||||
},
|
||||
:repository => {
|
||||
:name => bl.save_to_repository.name,
|
||||
:id => bl.save_to_repository.id
|
||||
},
|
||||
:type => :publish,
|
||||
:time_living => 2400 # 40 min
|
||||
}
|
||||
|
||||
packages = {:sources => [], :binaries => {:x86_64 => [], :i586 => []}}
|
||||
old_packages = {:sources => [], :binaries => {:x86_64 => [], :i586 => []}}
|
||||
build_list_ids = []
|
||||
|
||||
new_sources = {}
|
||||
build_lists.each do |bl|
|
||||
# remove duplicates of sources for different arches
|
||||
bl.packages.by_package_type('source').each{ |s| new_sources["#{s.fullname}"] = s.sha1 }
|
||||
fill_packages(bl, packages)
|
||||
bl.last_published.includes(:packages).limit(5).each{ |old_bl|
|
||||
fill_packages(old_bl, old_packages, :fullname)
|
||||
}
|
||||
build_list_ids << bl.id
|
||||
@redis.lpush(LOCKED_BUILD_LISTS, bl.id)
|
||||
end
|
||||
|
||||
packages[:sources] = new_sources.values
|
||||
Resque.push(
|
||||
worker_queue,
|
||||
'class' => worker_class,
|
||||
'args' => [options.merge({
|
||||
:packages => packages,
|
||||
:old_packages => old_packages,
|
||||
:build_list_ids => build_list_ids
|
||||
})]
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
def fill_packages(bl, results_map, field = :sha1)
|
||||
results_map[:sources] |= bl.packages.by_package_type('source').pluck(field) if field != :sha1
|
||||
results_map[:binaries][bl.arch.name.to_sym] |= bl.packages.by_package_type('binary').pluck(field)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -5,12 +5,12 @@ module AbfWorker
|
|||
# - #build_canceled
|
||||
|
||||
def abf_worker_log
|
||||
Resque.redis.get("abfworker::#{worker_queue('-')}-#{id}") || I18n.t('layout.build_lists.log.not_available')
|
||||
Resque.redis.get(service_queue) || I18n.t('layout.build_lists.log.not_available')
|
||||
end
|
||||
|
||||
def add_job_to_abf_worker_queue
|
||||
Resque.push(
|
||||
worker_queue,
|
||||
worker_queue_with_priority,
|
||||
'class' => worker_queue_class,
|
||||
'args' => [abf_worker_args]
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ module AbfWorker
|
|||
|
||||
def cancel_job
|
||||
deleted = Resque::Job.destroy(
|
||||
worker_queue,
|
||||
worker_queue_with_priority,
|
||||
worker_queue_class,
|
||||
abf_worker_args
|
||||
)
|
||||
|
@ -30,34 +30,29 @@ module AbfWorker
|
|||
true
|
||||
end
|
||||
|
||||
def worker_queue_with_priority(queue = nil)
|
||||
queue ||= abf_worker_base_queue
|
||||
queue << '_' << abf_worker_priority if abf_worker_priority.present?
|
||||
queue
|
||||
end
|
||||
|
||||
def worker_queue_class(queue_class = nil)
|
||||
queue_class ||= "AbfWorker::#{abf_worker_base_queue.classify}"
|
||||
queue_class << abf_worker_priority.capitalize
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def send_stop_signal
|
||||
Resque.redis.setex(
|
||||
live_inspector_queue,
|
||||
"#{service_queue}::live-inspector",
|
||||
240, # Data will be removed from Redis after 240 sec.
|
||||
'USR1' # Immediately kill child but don't exit
|
||||
)
|
||||
end
|
||||
|
||||
def live_inspector_queue
|
||||
q = 'abfworker::'
|
||||
q << worker_queue('-')
|
||||
q << '-'
|
||||
q << id.to_s
|
||||
q << '::live-inspector'
|
||||
q
|
||||
end
|
||||
|
||||
def worker_queue(delimiter = '_')
|
||||
a = []
|
||||
a << (is_a?(BuildList) ? 'rpm' : 'iso')
|
||||
a << 'worker'
|
||||
a.join(delimiter)
|
||||
end
|
||||
|
||||
def worker_queue_class
|
||||
is_a?(BuildList) ? 'AbfWorker::RpmWorker' : 'AbfWorker::IsoWorker'
|
||||
def service_queue
|
||||
"abfworker::#{abf_worker_base_queue.gsub(/\_/, '-')}-#{id}"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
module AbfWorker
|
||||
class PublishBuildListContainerObserver < AbfWorker::BaseObserver
|
||||
@queue = :publish_build_list_container_observer
|
||||
|
||||
def self.perform(options)
|
||||
bl = BuildList.find options['id']
|
||||
status = options['status'].to_i
|
||||
case status
|
||||
when COMPLETED
|
||||
bl.published
|
||||
update_results(bl, options)
|
||||
when FAILED
|
||||
bl.fail_publish
|
||||
update_results(bl, options)
|
||||
when CANCELED
|
||||
bl.fail_publish
|
||||
update_results(bl, options)
|
||||
end
|
||||
end
|
||||
|
||||
def self.update_results(subject, options)
|
||||
results = (subject.results || []).
|
||||
map{ |r| r if r['file_name'] !~ /^abfworker\:\:publish\-build\-list\-container\-worker.*\.log$/ }.
|
||||
compact
|
||||
results += options['results']
|
||||
sort_results_and_save(subject, results)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
module AbfWorker
|
||||
class PublishObserver < AbfWorker::BaseObserver
|
||||
@queue = :publish_observer
|
||||
|
||||
def self.perform(options)
|
||||
status = options['status'].to_i
|
||||
return if status == STARTED # do nothing when publication started
|
||||
build_lists = BuildList.where(:id => options['build_list_ids'])
|
||||
build_lists.each do |bl|
|
||||
update_results(bl, options)
|
||||
case status
|
||||
when COMPLETED
|
||||
bl.published
|
||||
when FAILED, CANCELED
|
||||
bl.fail_publish
|
||||
end
|
||||
AbfWorker::BuildListsPublishTaskManager.unlock_build_list bl
|
||||
end
|
||||
AbfWorker::BuildListsPublishTaskManager.unlock_rep_and_platform build_lists.first
|
||||
end
|
||||
|
||||
def self.update_results(subject, options)
|
||||
results = (subject.results || []).
|
||||
select{ |r| r['file_name'] !~ /^abfworker\:\:publish\-worker.*\.log$/ }
|
||||
results |= options['results']
|
||||
sort_results_and_save(subject, results)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -18,8 +18,6 @@ module AbfWorker
|
|||
bl.build_error
|
||||
item.update_attributes({:status => BuildServer::BUILD_ERROR})
|
||||
when STARTED
|
||||
bl.bs_id = bl.id
|
||||
bl.save!
|
||||
bl.start_build
|
||||
when CANCELED
|
||||
bl.build_canceled
|
||||
|
@ -48,14 +46,6 @@ module AbfWorker
|
|||
package.platform_id = bl.save_to_platform_id
|
||||
package.save!
|
||||
end
|
||||
|
||||
container = (options['results'] || []).
|
||||
select{ |r| r['file_name'] !~ /.*\.log$/ }.first
|
||||
sha1 = container ? container['sha1'] : nil
|
||||
if sha1
|
||||
bl.container_path = "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}"
|
||||
bl.save!
|
||||
end
|
||||
update_results(bl, options)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,15 +9,13 @@ class ApiDefender < Rack::Throttle::Hourly
|
|||
options = {
|
||||
:cache => Redis.new(:thread_safe => true),
|
||||
:key_prefix => :throttle,
|
||||
|
||||
# only 500 request per hour
|
||||
:max => 500
|
||||
:max => 500 # only 500 request per hour
|
||||
}
|
||||
@app, @options = app, options
|
||||
end
|
||||
|
||||
# this method checks if request needs throttling.
|
||||
# If so, it increases usage counter and compare it with maximum
|
||||
# this method checks if request needs throttling.
|
||||
# If so, it increases usage counter and compare it with maximum
|
||||
# allowed API calls. Returns true if a request can be handled.
|
||||
def allowed?(request)
|
||||
need_defense?(request) ? cache_incr(request) <= max_per_window : true
|
||||
|
@ -30,8 +28,9 @@ class ApiDefender < Rack::Throttle::Hourly
|
|||
# requests remaining does they have
|
||||
if need_defense?(request)
|
||||
heders['X-RateLimit-Limit'] = max_per_window.to_s
|
||||
heders['X-RateLimit-Remaining'] = ([0, max_per_window - (cache_get(cache_key(request)).to_i rescue 1)].max).to_s
|
||||
heders['X-RateLimit-Remaining'] = ([0, max_per_window - (cache_get(choice_key(request)).to_i rescue 1)].max).to_s
|
||||
end
|
||||
@is_authorized = @user = nil
|
||||
[status, heders, body]
|
||||
end
|
||||
|
||||
|
@ -40,14 +39,34 @@ class ApiDefender < Rack::Throttle::Hourly
|
|||
key = cache_key(request)
|
||||
count = cache.incr(key)
|
||||
cache.expire(key, 1.day) if count == 1
|
||||
|
||||
if @user
|
||||
count = cache.incr(choice_key(request))
|
||||
cache.expire(key, 1.day) if count == 1
|
||||
end
|
||||
count
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# only API calls should be throttled
|
||||
def need_defense?(request)
|
||||
request.env['PATH_INFO'] =~ /^\/api\/v1\//
|
||||
end
|
||||
# only API calls should be throttled
|
||||
def need_defense?(request)
|
||||
request.env['PATH_INFO'] =~ /^\/api\/v1\// && !system_user?(request)
|
||||
end
|
||||
|
||||
end
|
||||
def authorized?(request)
|
||||
return @is_authorized if @is_authorized
|
||||
auth = Rack::Auth::Basic::Request.new(request.env)
|
||||
@user = User.auth_by_token_or_login_pass(*auth.credentials) if auth.provided? and auth.basic?
|
||||
@is_authorized = true # cache
|
||||
end
|
||||
|
||||
def choice_key request
|
||||
return cache_key(request) unless @user
|
||||
[@options[:key_prefix], @user.uname, Time.now.strftime('%Y-%m-%dT%H')].join(':')
|
||||
end
|
||||
|
||||
def system_user? request
|
||||
authorized?(request) && @user.try(:system?)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ module Modules
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :create_personal_repository
|
||||
after_create :create_personal_repository, :unless => :system?
|
||||
end
|
||||
|
||||
def create_personal_repository
|
||||
|
|
|
@ -12,9 +12,7 @@ module Grack
|
|||
return render_not_found if project.blank?
|
||||
|
||||
return ::Rack::Auth::Basic.new(@app) do |u, p|
|
||||
user = (User.where(:authentication_token => u).first ||
|
||||
User.find_for_database_authentication(:login => u)) and
|
||||
!user.access_locked? and (user.authentication_token == u or user.valid_password?(p)) and
|
||||
user = User.auth_by_token_or_login_pass(u, p) and
|
||||
ability = ::Ability.new(user) and ability.can?(action, project) # project.members.include?(user)
|
||||
end.call(env) unless project.public? and read? # need auth
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|||
:notification,
|
||||
:iso_worker_observer,
|
||||
:rpm_worker_observer,
|
||||
:publish_build_list_container_observer
|
||||
:publish_observer
|
||||
].join(',')
|
||||
run "cd #{fetch :current_path} && COUNT=#{workers_count} QUEUE=#{queue} #{rails_env} BACKGROUND=yes bundle exec rake resque:workers"
|
||||
end
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
namespace :new_core do
|
||||
desc 'Sets bs_id field for all BuildList which use new_core'
|
||||
task :update_bs_id => :environment do
|
||||
say "[#{Time.zone.now}] Starting to update bs_id..."
|
||||
|
||||
BuildList.select(:id).
|
||||
where(:new_core => true, :bs_id => nil).
|
||||
find_in_batches(:batch_size => 500) do | bls |
|
||||
|
||||
puts "[#{Time.zone.now}] - where build_lists.id from #{bls.first.id} to #{bls.last.id}"
|
||||
BuildList.where(:id => bls.map(&:id), :bs_id => nil).
|
||||
update_all("bs_id = id")
|
||||
end
|
||||
|
||||
say "[#{Time.zone.now}] done"
|
||||
end
|
||||
|
||||
desc 'Publish mass-build 73'
|
||||
task :publish_mass_build_73 => :environment do
|
||||
say "[#{Time.zone.now}] Starting to publish mass-build 317..."
|
||||
|
||||
bl = BuildList.where(:mass_build_id => 73).first
|
||||
platform_repository_folder = "#{bl.save_to_platform.path}/repository"
|
||||
BuildList.where(:mass_build_id => 73).
|
||||
where(:status => [
|
||||
BuildServer::SUCCESS,
|
||||
BuildList::FAILED_PUBLISH
|
||||
]).
|
||||
order(:id).
|
||||
find_in_batches(:batch_size => 1) do | bls |
|
||||
|
||||
bl = bls.first
|
||||
puts "[#{Time.zone.now}] - where build_lists.id #{bl.id}"
|
||||
|
||||
sha1 = bl.results.find{ |r| r['file_name'] =~ /.*\.tar\.gz$/ }['sha1']
|
||||
|
||||
system "cd #{platform_repository_folder} && curl -L -O #{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}"
|
||||
system "cd #{platform_repository_folder} && tar -xzf #{sha1}"
|
||||
system "rm -f #{platform_repository_folder}/#{sha1}"
|
||||
|
||||
archive_folder = "#{platform_repository_folder}/archives"
|
||||
system "sudo chown root:root #{archive_folder}/SRC_RPM/*"
|
||||
system "sudo chmod 0666 #{archive_folder}/SRC_RPM/*"
|
||||
system "sudo chown root:root #{archive_folder}/RPM/*"
|
||||
system "sudo chmod 0666 #{archive_folder}/RPM/*"
|
||||
|
||||
system "sudo mv #{archive_folder}/SRC_RPM/* #{platform_repository_folder}/SRPMS/main/release/"
|
||||
system "sudo mv #{archive_folder}/RPM/* #{platform_repository_folder}/#{bl.arch.name}/main/release/"
|
||||
|
||||
system "sudo rm -rf #{archive_folder}"
|
||||
bl.update_column(:status, BuildList::BUILD_PUBLISH)
|
||||
end
|
||||
|
||||
say "[#{Time.zone.now}] done"
|
||||
end
|
||||
|
||||
desc 'Extracts all rpms from BuildList container and updates BuildList::Package#sha1 field'
|
||||
task :update_packages => :environment do
|
||||
say "[#{Time.zone.now}] Starting to extract rpms..."
|
||||
|
||||
token = User.find_by_uname('rosa_system').authentication_token
|
||||
BuildList.where(:new_core => true).
|
||||
where(:status => [
|
||||
BuildServer::SUCCESS,
|
||||
BuildList::FAILED_PUBLISH,
|
||||
BuildList::BUILD_PUBLISHED,
|
||||
BuildList::BUILD_PUBLISH
|
||||
]).
|
||||
order(:id).
|
||||
find_in_batches(:batch_size => 100) do | build_lists |
|
||||
|
||||
build_lists.each do | bl |
|
||||
puts "[#{Time.zone.now}] - where build_lists.id #{bl.id}"
|
||||
|
||||
sha1 = (bl.results.find{ |r| r['file_name'] =~ /.*\.tar\.gz$/ } || {})['sha1']
|
||||
next unless sha1
|
||||
dir = Dir.mktmpdir('update-packages-', "#{APP_CONFIG['root_path']}")
|
||||
begin
|
||||
system "cd #{dir} && curl -L -O #{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}; tar -xzf #{sha1}"
|
||||
system "rm -f #{dir}/#{sha1}"
|
||||
|
||||
extract_rpms_and_update_packages("#{dir}/archives/SRC_RPM", bl, 'source', token)
|
||||
extract_rpms_and_update_packages("#{dir}/archives/RPM", bl, 'binary', token)
|
||||
ensure
|
||||
# remove the directory.
|
||||
`sudo rm -rf #{dir}`
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
say "[#{Time.zone.now}] done"
|
||||
end
|
||||
|
||||
def extract_rpms_and_update_packages(dir, bl, package_type, token)
|
||||
Dir.glob("#{dir}/*.rpm") do |rpm_file|
|
||||
fullname = File.basename rpm_file
|
||||
package = bl.packages.by_package_type(package_type).find{ |p| p.fullname == fullname }
|
||||
next unless package
|
||||
|
||||
package.sha1 = Digest::SHA1.file(rpm_file).hexdigest
|
||||
if %x[ curl #{APP_CONFIG['file_store_url']}/api/v1/file_stores.json?hash=#{package.sha1} ] == '[]'
|
||||
system "curl --user #{token}: -POST -F 'file_store[file]=@#{rpm_file}' #{APP_CONFIG['file_store_url']}/api/v1/upload"
|
||||
end
|
||||
package.save!
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -108,7 +108,7 @@ describe Api::V1::BuildListsController do
|
|||
|
||||
context "do cancel" do
|
||||
def do_cancel
|
||||
get :cancel, :id => @build_list, :format => :json
|
||||
put :cancel, :id => @build_list, :format => :json
|
||||
end
|
||||
|
||||
context 'if user is project owner' do
|
||||
|
@ -161,7 +161,7 @@ describe Api::V1::BuildListsController do
|
|||
|
||||
context "do publish" do
|
||||
def do_publish
|
||||
get :publish, :id => @build_list, :format => :json
|
||||
put :publish, :id => @build_list, :format => :json
|
||||
end
|
||||
|
||||
context 'if user is project owner' do
|
||||
|
@ -220,7 +220,7 @@ describe Api::V1::BuildListsController do
|
|||
end
|
||||
|
||||
def do_reject_publish
|
||||
get :reject_publish, :id => @build_list, :format => :json
|
||||
put :reject_publish, :id => @build_list, :format => :json
|
||||
end
|
||||
|
||||
context 'if user is project owner' do
|
||||
|
@ -397,7 +397,7 @@ describe Api::V1::BuildListsController do
|
|||
@build_list2.project.update_column(:visibility, 'hidden')
|
||||
|
||||
project = FactoryGirl.create(:project_with_commit, :visibility => 'hidden', :owner => @user)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core, :project => project)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core_with_attaching_project, :project => project)
|
||||
|
||||
@build_list4 = FactoryGirl.create(:build_list_core)
|
||||
@build_list4.project.update_column(:visibility, 'hidden')
|
||||
|
|
|
@ -130,7 +130,7 @@ describe Projects::BuildListsController do
|
|||
@build_list2.project.update_column(:visibility, 'hidden')
|
||||
|
||||
project = FactoryGirl.create(:project_with_commit, :visibility => 'hidden', :owner => @user)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core, :project => project)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core_with_attaching_project, :project => project)
|
||||
|
||||
@build_list4 = FactoryGirl.create(:build_list_core)
|
||||
@build_list4.project.update_column(:visibility, 'hidden')
|
||||
|
@ -218,7 +218,7 @@ describe Projects::BuildListsController do
|
|||
@build_list2.project.update_column(:visibility, 'hidden')
|
||||
|
||||
project = FactoryGirl.create(:project_with_commit, :visibility => 'hidden', :owner => @user)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core, :project => project)
|
||||
@build_list3 = FactoryGirl.create(:build_list_core_with_attaching_project, :project => project)
|
||||
|
||||
@build_list4 = FactoryGirl.create(:build_list_core)
|
||||
@build_list4.project.update_column(:visibility, 'hidden')
|
||||
|
|
|
@ -15,6 +15,7 @@ describe Projects::Git::TreesController do
|
|||
|
||||
context 'for guest' do
|
||||
it 'should be able to perform archive action with anonymous acccess', :anonymous_access => true do
|
||||
stub(controller).render
|
||||
fill_project @project
|
||||
get :archive, @params.merge(:format => 'tar.gz')
|
||||
response.should be_success
|
||||
|
@ -49,6 +50,7 @@ describe Projects::Git::TreesController do
|
|||
end
|
||||
|
||||
it 'should be able to perform archive action' do
|
||||
stub(controller).render
|
||||
fill_project @project
|
||||
@user = FactoryGirl.create(:user)
|
||||
set_session_for(@user)
|
||||
|
|
|
@ -18,10 +18,18 @@ FactoryGirl.define do
|
|||
commit_hash {|bl| Grit::Repo.new(bl.project.path).commits.first.id}
|
||||
end
|
||||
|
||||
factory :build_list_with_attaching_project, :parent => :build_list do
|
||||
before(:create) { |bl| attach_project_to_build_list bl }
|
||||
end
|
||||
|
||||
factory :build_list_core, :parent => :build_list do
|
||||
bs_id { FactoryGirl.generate(:integer) }
|
||||
end
|
||||
|
||||
factory :build_list_core_with_attaching_project, :parent => :build_list_core do
|
||||
before(:create) { |bl| attach_project_to_build_list bl }
|
||||
end
|
||||
|
||||
factory :build_list_by_group_project, :parent => :build_list_core do
|
||||
project { |bl|
|
||||
pr = FactoryGirl.create(:group_project_with_commit)
|
||||
|
@ -41,3 +49,8 @@ FactoryGirl.define do
|
|||
package_type "source"
|
||||
end
|
||||
end
|
||||
|
||||
def attach_project_to_build_list(bl)
|
||||
bl.save_to_platform ||= FactoryGirl.create(:platform_with_repos)
|
||||
bl.project.repositories << bl.save_to_platform.repositories.first
|
||||
end
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ApiDefender do
|
||||
def get_basic_auth user = @user, by_token = false, by_email = false
|
||||
u,pass = if by_token
|
||||
[user.authentication_token, '']
|
||||
elsif by_email
|
||||
[user.email, @password]
|
||||
else
|
||||
[user.uname, @password]
|
||||
end
|
||||
ActionController::HttpAuthentication::Basic.encode_credentials u, pass
|
||||
end
|
||||
|
||||
def get_request auth_user = nil, by_token = false, by_email = false
|
||||
auth = auth_user ? {'HTTP_AUTHORIZATION' => get_basic_auth(auth_user, by_token, by_email)} : {}
|
||||
get "/api/v1/users/#{@user.id}.json", {}, auth
|
||||
end
|
||||
|
||||
def get_request2 auth_user = nil, by_token = false, by_email = false
|
||||
auth_user = FactoryGirl.create(:user) if !auth_user && APP_CONFIG['anonymous_access'] == false
|
||||
get_request auth_user, by_token, by_email
|
||||
end
|
||||
|
||||
before do
|
||||
stub_symlink_methods && stub_redis
|
||||
@redis = Redis.new
|
||||
@password = '123456'
|
||||
@rate_limit = 3 # dont forget change in max_per_window
|
||||
|
||||
ApiDefender.class_eval("def cache; Redis.new; end; def max_per_window; return #{@rate_limit}; end;")
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
@user = FactoryGirl.create :user, :password => @password
|
||||
@system_user = FactoryGirl.create :user, :role => 'system'
|
||||
end
|
||||
|
||||
if APP_CONFIG['anonymous_access'] == true
|
||||
context 'for anonymous user' do
|
||||
it "should return the total limit" do
|
||||
get_request
|
||||
response.headers['X-RateLimit-Limit'].should == @rate_limit.to_s
|
||||
end
|
||||
|
||||
it "should return the correct limit usage for anonymous user" do
|
||||
get_request
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should return the correct limit usage for anonymous user after authenticated access" do
|
||||
get_request @user
|
||||
get_request
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-2).to_s
|
||||
end
|
||||
|
||||
it "should forbidden anonymous user after exceeding limit rate" do
|
||||
(@rate_limit+1).times {get_request}
|
||||
response.status.should == 403
|
||||
end
|
||||
end
|
||||
else
|
||||
it "should forbidden anonymous access" do
|
||||
get_request
|
||||
response.status.should == 401
|
||||
end
|
||||
end
|
||||
|
||||
context 'for user' do
|
||||
it "should return the correct limit usage for auth user" do
|
||||
get_request @user
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should allow auth by uname and password" do
|
||||
(@rate_limit+1).times {get_request2}
|
||||
get_request @user
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should allow auth by email and password" do
|
||||
(@rate_limit+1).times {get_request2}
|
||||
get_request @user, false, true
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should allow auth by token" do
|
||||
(@rate_limit+1).times {get_request2}
|
||||
get_request @user, true
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should return the correct limit usage for auth user after other user" do
|
||||
get_request2
|
||||
get_request @user
|
||||
response.headers['X-RateLimit-Remaining'].should == (@rate_limit-1).to_s
|
||||
end
|
||||
|
||||
it "should forbidden user after exceeding limit rate" do
|
||||
(@rate_limit+1).times {get_request @user}
|
||||
response.status.should == 403
|
||||
end
|
||||
|
||||
it "should not forbidden user after exceeding limit rate of the other user" do
|
||||
(@rate_limit+1).times {get_request2}
|
||||
get_request @user
|
||||
response.status.should == 200
|
||||
end
|
||||
end
|
||||
|
||||
context 'for system user' do
|
||||
it "should not return the limit usage for system user" do
|
||||
get_request @system_user, true
|
||||
response.headers['X-RateLimit-Limit'].should_not == @rate_limit.to_s
|
||||
end
|
||||
|
||||
it "should not forbidden system user" do
|
||||
(@rate_limit+1).times {get_request @system_user, true}
|
||||
response.status.should == 200
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,6 +3,18 @@ require 'spec_helper'
|
|||
|
||||
describe BuildList do
|
||||
|
||||
context 'validates that repository contains project' do
|
||||
it 'when repository contains project' do
|
||||
bl = FactoryGirl.build(:build_list)
|
||||
bl.valid?.should be_true
|
||||
end
|
||||
it 'when repository does not contain project' do
|
||||
bl = FactoryGirl.build(:build_list)
|
||||
bl.project.repositories = []
|
||||
bl.valid?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
context "#notify_users" do
|
||||
before { stub_symlink_methods }
|
||||
let!(:user) { FactoryGirl.create(:user) }
|
||||
|
@ -128,10 +140,12 @@ describe BuildList do
|
|||
end
|
||||
|
||||
it "doesn't get 2 notification by email when user associated to project and created task" do
|
||||
bl = FactoryGirl.create(:build_list_core,
|
||||
project = FactoryGirl.create(:project_with_commit, :owner => user)
|
||||
bl = FactoryGirl.create(:build_list_core_with_attaching_project,
|
||||
:user => user,
|
||||
:auto_publish => true,
|
||||
:project => FactoryGirl.create(:project_with_commit, :owner => user))
|
||||
:project => project
|
||||
)
|
||||
FactoryGirl.create(:build_list_package, :build_list => bl, :project => bl.project)
|
||||
bl.update_attributes({:commit_hash => bl.project.repo.commits('master').last.id,
|
||||
:status => BuildList::BUILD_PUBLISH}, :without_protection => true)
|
||||
|
|
|
@ -168,7 +168,7 @@ describe CanCan do
|
|||
|
||||
[:new, :create].each do |action|
|
||||
it "should be able to #{action} build_list" do
|
||||
@build_list = FactoryGirl.create(:build_list, :project => @project)
|
||||
@build_list = FactoryGirl.create(:build_list_with_attaching_project, :project => @project)
|
||||
@ability.should be_able_to(action, @build_list)
|
||||
end
|
||||
end
|
||||
|
@ -187,7 +187,7 @@ describe CanCan do
|
|||
|
||||
[:new, :create].each do |action|
|
||||
it "should be able to #{action} build_list" do
|
||||
@build_list = FactoryGirl.create(:build_list, :project => @project)
|
||||
@build_list = FactoryGirl.create(:build_list_with_attaching_project, :project => @project)
|
||||
@ability.should be_able_to(action, @build_list)
|
||||
end
|
||||
end
|
||||
|
@ -217,7 +217,7 @@ describe CanCan do
|
|||
|
||||
[:new, :create].each do |action|
|
||||
it "should be able to #{action} build_list" do
|
||||
@build_list = FactoryGirl.create(:build_list, :project => @project)
|
||||
@build_list = FactoryGirl.create(:build_list_with_attaching_project, :project => @project)
|
||||
@ability.should be_able_to(action, @build_list)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,13 +21,18 @@ describe Issue do
|
|||
before(:each) do
|
||||
set_data
|
||||
@project = FactoryGirl.create(:project, :owner => @user)
|
||||
create_issue(@stranger)
|
||||
end
|
||||
|
||||
it 'should send an e-mail' do
|
||||
create_issue(@stranger)
|
||||
ActionMailer::Base.deliveries.count.should == 1
|
||||
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
|
||||
end
|
||||
|
||||
it 'should not send an e-mail to creator' do
|
||||
create_issue(@user)
|
||||
ActionMailer::Base.deliveries.count.should == 0
|
||||
end
|
||||
end
|
||||
|
||||
context 'for member-group' do
|
||||
|
@ -47,6 +52,13 @@ describe Issue do
|
|||
ActionMailer::Base.deliveries.count.should == 3 # 1 owner + 2 group member. enough?
|
||||
end
|
||||
|
||||
it 'should send an e-mail to all members of the admin group except creator' do
|
||||
@project.relations.create!(:actor_type => 'Group', :actor_id => @group.id, :role => 'admin')
|
||||
|
||||
create_issue(@group.owner)
|
||||
ActionMailer::Base.deliveries.count.should == 2 # 1 owner + 1 group member. enough?
|
||||
end
|
||||
|
||||
it 'should not send an e-mail to members of the reader group' do
|
||||
@project.relations.create!(:actor_type => 'Group', :actor_id => @group.id, :role => 'reader')
|
||||
|
||||
|
@ -68,6 +80,11 @@ describe Issue do
|
|||
ActionMailer::Base.deliveries.count.should == 1
|
||||
ActionMailer::Base.deliveries.last.to.include?(@user.email).should == true
|
||||
end
|
||||
|
||||
it 'should not send an e-mail to creator' do
|
||||
create_issue(@user)
|
||||
ActionMailer::Base.deliveries.count.should == 0
|
||||
end
|
||||
end
|
||||
|
||||
context 'for reader of the group' do
|
||||
|
|
|
@ -67,10 +67,15 @@ end
|
|||
|
||||
init_test_root
|
||||
|
||||
def stub_redis
|
||||
redis_instance = MockRedis.new
|
||||
stub(Redis).new { redis_instance }
|
||||
end
|
||||
|
||||
def fill_project project
|
||||
%x(mkdir -p #{project.path} && cp -Rf #{Rails.root}/spec/tests.git/* #{project.path}) # maybe FIXME ?
|
||||
end
|
||||
|
||||
def clean_projects_dir
|
||||
FileUtils.rm_rf "#{APP_CONFIG['git_path']}"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue