[issue #133] Merge branch 'master' into 133-editing_from_web
Conflicts: db/schema.rb
4
Gemfile
|
@ -1,7 +1,6 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
gem 'rails', '3.0.11' #, :git => 'git://github.com/rails/rails.git'
|
||||
gem 'shotgun'
|
||||
|
||||
gem 'pg', '~> 0.11.0'
|
||||
gem 'silent-postgres', '~> 0.1.1'
|
||||
|
@ -54,13 +53,14 @@ end
|
|||
gem 'newrelic_rpm'
|
||||
|
||||
group :development do
|
||||
# gem 'letter_opener'
|
||||
gem 'mailcatcher' # 'letter_opener'
|
||||
gem 'rails3-generators'
|
||||
gem 'web-app-theme'
|
||||
gem 'hpricot'
|
||||
gem 'ruby_parser'
|
||||
|
||||
gem 'hirb'
|
||||
gem 'shotgun'
|
||||
|
||||
# deploy
|
||||
gem 'capistrano', :require => false
|
||||
|
|
22
Gemfile.lock
|
@ -85,6 +85,7 @@ GEM
|
|||
diff-lcs (1.1.3)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
eventmachine (0.12.10)
|
||||
expression_parser (0.9.0)
|
||||
factory_girl (2.3.2)
|
||||
activesupport
|
||||
|
@ -121,6 +122,16 @@ GEM
|
|||
i18n (>= 0.4.0)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mailcatcher (0.2.4)
|
||||
eventmachine
|
||||
haml
|
||||
i18n
|
||||
json
|
||||
mail
|
||||
sinatra
|
||||
skinny (>= 0.1.2)
|
||||
sqlite3-ruby
|
||||
thin
|
||||
meta-tags (1.2.4)
|
||||
actionpack
|
||||
mime-types (1.17.2)
|
||||
|
@ -212,7 +223,17 @@ GEM
|
|||
sinatra (1.2.8)
|
||||
rack (~> 1.1)
|
||||
tilt (>= 1.2.2, < 2.0)
|
||||
skinny (0.2.0)
|
||||
eventmachine (~> 0.12)
|
||||
thin (~> 1.2)
|
||||
sqlite3 (1.3.5)
|
||||
sqlite3-ruby (1.3.3)
|
||||
sqlite3 (>= 1.3.3)
|
||||
state_machine (1.1.2)
|
||||
thin (1.3.1)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 0.12.6)
|
||||
rack (>= 1.0.0)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
treetop (1.4.10)
|
||||
|
@ -260,6 +281,7 @@ DEPENDENCIES
|
|||
hirb
|
||||
hpricot
|
||||
jammit
|
||||
mailcatcher
|
||||
meta-tags (~> 1.2.4)
|
||||
newrelic_rpm
|
||||
omniauth (~> 1.0.1)
|
||||
|
|
|
@ -49,7 +49,7 @@ class BuildListsController < ApplicationController
|
|||
Arch.where(:id => params[:arches]).each do |arch|
|
||||
Platform.main.where(:id => params[:bpls]).each do |bpl|
|
||||
@build_list = @project.build_lists.build(params[:build_list])
|
||||
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id
|
||||
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version
|
||||
@build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user
|
||||
flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl}
|
||||
if @build_list.save
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class RegisterRequestsController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
|
||||
before_filter :find_register_request, :only => [:approve, :reject]
|
||||
|
||||
def index
|
||||
@register_requests = @register_requests.unprocessed.paginate(:page => params[:page])
|
||||
end
|
||||
|
||||
def new
|
||||
# render :layout => 'sessions'
|
||||
redirect_to '/invite.html'
|
||||
end
|
||||
|
||||
def show_message
|
||||
end
|
||||
|
||||
def create
|
||||
RegisterRequest.create(params[:register_request])
|
||||
redirect_to '/thanks.html' #show_message_register_requests_path
|
||||
end
|
||||
|
||||
def update
|
||||
if params[:update_type].present? and params[:request_ids].present?
|
||||
updates = RegisterRequest.where(:id => params[:request_ids])
|
||||
case params[:update_type]
|
||||
when 'approve' # see approve method
|
||||
updates.each {|req| req.update_attributes(:approved => true, :rejected => false)}
|
||||
when 'reject' # see reject method
|
||||
updates.each {|req| req.update_attributes(:approved => false, :rejected => true)}
|
||||
end
|
||||
end
|
||||
redirect_to :action => :index
|
||||
end
|
||||
|
||||
def approve
|
||||
@register_request.update_attributes(:approved => true, :rejected => false)
|
||||
redirect_to :action => :index
|
||||
end
|
||||
|
||||
def reject
|
||||
@register_request.update_attributes(:approved => false, :rejected => true)
|
||||
redirect_to :action => :index
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def find_register_request
|
||||
@register_request = RegisterRequest.find(params[:register_request_id])
|
||||
end
|
||||
end
|
|
@ -33,4 +33,9 @@ class UserMailer < ActionMailer::Base
|
|||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
def invite_approve_notification(register_request)
|
||||
@register_request = register_request
|
||||
mail :to => register_request.email, :subject => I18n.t("notifications.subjects.invite_approve_notification")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class Ability
|
|||
can :manage, :all
|
||||
cannot :destroy, Subscribe
|
||||
cannot :create, Subscribe
|
||||
cannot :create, RegisterRequest
|
||||
else
|
||||
# Shared rights between guests and registered users
|
||||
can :forbidden, Platform
|
||||
|
@ -26,6 +27,7 @@ class Ability
|
|||
|
||||
if user.guest? # Guest rights
|
||||
can :create, User
|
||||
can [:create, :show_message], RegisterRequest
|
||||
else # Registered user rights
|
||||
can [:show, :autocomplete_user_uname], User
|
||||
|
||||
|
@ -67,7 +69,7 @@ class Ability
|
|||
can :autocomplete_user_uname, Platform
|
||||
|
||||
# TODO delegate to platform?
|
||||
can :read, Repository, :visibility => 'open'
|
||||
can :read, Repository, :platform => {:visibility => 'open'}
|
||||
can :read, Repository, :owner_type => 'User', :owner_id => user.id
|
||||
can :read, Repository, :owner_type => 'Group', :owner_id => user.group_ids
|
||||
can(:read, Repository, read_relations_for('repositories')) {|repository| local_reader? repository}
|
||||
|
@ -97,6 +99,7 @@ class Ability
|
|||
can(:update, Comment) {|comment| comment.user_id == user.id or local_admin?(comment.project || comment.commentable.project)}
|
||||
#cannot :manage, Comment, :commentable => {:project => {:has_issues => false}} # switch off issues
|
||||
cannot(:manage, Comment) {|comment| comment.commentable_type == 'Issue' && !comment.commentable.project.has_issues} # switch off issues
|
||||
cannot :manage, RegisterRequest
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@ class Group < ActiveRecord::Base
|
|||
|
||||
has_many :own_projects, :as => :owner, :class_name => 'Project'
|
||||
|
||||
has_many :relations, :as => :object, :dependent => :destroy
|
||||
has_many :objects, :as => :target, :class_name => 'Relation'
|
||||
has_many :targets, :as => :object, :class_name => 'Relation'
|
||||
|
||||
has_many :members, :through => :objects, :source => :object, :source_type => 'User', :autosave => true
|
||||
has_many :projects, :through => :targets, :source => :target, :source_type => 'Project', :autosave => true
|
||||
has_many :platforms, :through => :targets, :source => :target, :source_type => 'Platform', :autosave => true
|
||||
has_many :platforms, :through => :targets, :source => :target, :source_type => 'Platform', :autosave => true, :dependent => :destroy
|
||||
has_many :repositories, :through => :targets, :source => :target, :source_type => 'Repository', :autosave => true
|
||||
has_many :relations, :as => :object, :dependent => :destroy
|
||||
|
||||
validates :name, :owner, :presence => true
|
||||
validates :uname, :presence => true, :uniqueness => {:case_sensitive => false}, :format => { :with => /^[a-z0-9_]+$/ }
|
||||
|
@ -20,6 +20,7 @@ class Group < ActiveRecord::Base
|
|||
attr_readonly :uname, :own_projects_count
|
||||
|
||||
delegate :ssh_key, :to => :owner
|
||||
delegate :email, :to => :owner
|
||||
|
||||
after_create :add_owner_to_members
|
||||
after_initialize lambda {|r| r.name ||= r.uname } # default
|
||||
|
|
|
@ -61,14 +61,14 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def build_for(platform, user)
|
||||
def build_for(platform, user)
|
||||
build_lists.create do |bl|
|
||||
bl.pl = platform
|
||||
bl.bpl = platform
|
||||
bl.update_type = 'recommended'
|
||||
bl.arch = Arch.find_by_name('x86_64') # Return i586 after mass rebuild
|
||||
# FIXME: Need to set "latest_#{platform.name}"
|
||||
bl.project_version = "latest_mandriva2011"
|
||||
bl.project_version = "latest_import_mandriva2011"
|
||||
bl.build_requires = false # already set as db default
|
||||
bl.user = user
|
||||
bl.auto_publish = true # already set as db default
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
class RegisterRequest < ActiveRecord::Base
|
||||
default_scope order('created_at ASC')
|
||||
|
||||
scope :rejected, where(:rejected => true)
|
||||
scope :approved, where(:approved => true)
|
||||
scope :unprocessed, where(:approved => false, :rejected => false)
|
||||
|
||||
# before_create :generate_token
|
||||
before_update :invite_approve_notification
|
||||
|
||||
validates :email, :presence => true, :uniqueness => {:case_sensitive => false}, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
|
||||
|
||||
protected
|
||||
|
||||
def generate_token
|
||||
self.token = Digest::SHA1.hexdigest(name + email + Time.now.to_s + rand.to_s)
|
||||
end
|
||||
|
||||
def invite_approve_notification
|
||||
if approved_changed? and approved == true
|
||||
generate_token
|
||||
UserMailer.invite_approve_notification(self).deliver
|
||||
end
|
||||
end
|
||||
end
|
|
@ -57,7 +57,7 @@ class Repository < ActiveRecord::Base
|
|||
if result == BuildServer::SUCCESS
|
||||
return true
|
||||
else
|
||||
raise "Failed to delete repository #{name} inside platform #{platform.name}."
|
||||
raise "Failed to delete repository #{name} inside platform #{platform.name} with code #{result}."
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ class User < ActiveRecord::Base
|
|||
LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']]
|
||||
LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
|
||||
|
||||
devise :database_authenticatable, :registerable, :omniauthable, # :token_authenticatable, :encryptable, :timeoutable
|
||||
devise :database_authenticatable, :registerable, #:omniauthable, # :token_authenticatable, :encryptable, :timeoutable
|
||||
:recoverable, :rememberable, :validatable #, :trackable, :confirmable, :lockable
|
||||
|
||||
has_one :notifier, :class_name => 'Settings::Notifier' #:notifier
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
%h2= title t("devise.registrations.sign_up_header")
|
||||
.content
|
||||
= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "form" }) do |f|
|
||||
= hidden_field_tag :invitation_token, @invitation_token
|
||||
- if resource.errors.present?
|
||||
.flash
|
||||
.message.error= resource.errors.full_messages.map { |msg| content_tag(:p, msg) }.join.html_safe
|
||||
|
@ -16,7 +17,7 @@
|
|||
.left
|
||||
= f.label :email, :class => "label"
|
||||
.right
|
||||
= f.text_field :email, :class => "text_field"
|
||||
= f.text_field :email, :class => "text_field", :readonly => 'readonly'
|
||||
|
||||
.group.wat-cf
|
||||
.left
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
- if controller_name != 'sessions'
|
||||
= link_to t("layout.devise.shared_links.sign_in"), new_session_path(resource_name), :class => "text_button_padding link_button"
|
||||
- if devise_mapping.registerable? && controller_name != 'registrations'
|
||||
= link_to t("layout.devise.shared_links.sign_up"), new_registration_path(resource_name), :class => "text_button_padding link_button"
|
||||
=# link_to t("layout.devise.shared_links.sign_up"), new_registration_path(resource_name), :class => "text_button_padding link_button"
|
||||
= link_to t("layout.devise.shared_links.sign_up"), new_register_request_path, :class => "text_button_padding link_button" # to prereg form
|
||||
- if devise_mapping.recoverable? && controller_name != 'passwords'
|
||||
= link_to t("layout.devise.shared_links.forgot_password"), new_password_path(resource_name), :class => "text_button_padding link_button"
|
||||
- if devise_mapping.confirmable? && controller_name != 'confirmations'
|
||||
= link_to t("layout.devise.shared_links.confirm_again"), new_confirmation_path(resource_name), :class => "text_button_padding link_button"
|
||||
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
|
||||
= link_to t("layout.devise.shared_links.unlock"), new_unlock_path(resource_name), :class => "text_button_padding link_button"
|
||||
- if devise_mapping.omniauthable?
|
||||
-# if devise_mapping.omniauthable?
|
||||
- resource_class.omniauth_providers.each do |provider|
|
||||
= link_to t("layout.devise.shared_links.sign_in_through", :provider => provider.to_s.classify), omniauth_authorize_path(resource_name, provider), :class => "text_button_padding link_button"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
= surround '[', ']' do
|
||||
= I18n.t "event_log.controllers.#{el.controller.underscore}", :default => lambda{el.controller}
|
||||
= I18n.t "event_log.controllers.#{el.controller.underscore}", :default => el.controller
|
||||
= I18n.t "event_log.actions.#{el.controller.underscore}.#{el.action}", :default => :"event_log.actions.#{el.action}"
|
||||
- if el.object_id.present? and el.object_type.present?
|
||||
= I18n.t "activerecord.models.#{el.object_type.underscore}"
|
||||
= el.object_name
|
||||
= "(id##{el.object_id})" # link_to "id##{el.object_id}", el.object
|
||||
= el.message
|
||||
= el.message
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
.block
|
||||
.secondary-navigation
|
||||
%ul.wat-cf
|
||||
%li.first= link_to t("layout.users.list"), users_path
|
||||
%li= link_to t("layout.users.new"), new_user_path
|
||||
%li.active= link_to t("layout.users.register_requests"), register_requests_path
|
||||
.content
|
||||
%h2.title
|
||||
= t("layout.register_request.list_header")
|
||||
.inner
|
||||
= form_tag register_requests_path, :method => :put, :class => 'update_form' do
|
||||
= hidden_field_tag 'update_type'
|
||||
%table.table
|
||||
%tr
|
||||
%th
|
||||
%th= t("activerecord.attributes.register_request.name")
|
||||
%th= t("activerecord.attributes.register_request.email")
|
||||
%th= t("activerecord.attributes.register_request.interest")
|
||||
%th= t("activerecord.attributes.register_request.more")
|
||||
%th= t("activerecord.attributes.register_request.created_at")
|
||||
%th
|
||||
- @register_requests.each do |request|
|
||||
%tr{:class => cycle("odd", "even")}
|
||||
%td= check_box_tag 'request_ids[]', request.id
|
||||
%td= request.name
|
||||
%td= request.email
|
||||
%td= request.interest
|
||||
%td= request.more
|
||||
%td= request.created_at
|
||||
%td
|
||||
= link_to t("layout.approve"), register_request_approve_path(request) if can? :approve, request
|
||||
|
|
||||
= link_to t("layout.reject"), register_request_reject_path(request) if can? :reject, request
|
||||
.actions-bar.wat-cf
|
||||
.actions
|
||||
<input type='button' id='approve_registration' value="Approve Selected" />
|
||||
<input type='button' id='reject_registration' value="Reject Selected" />
|
||||
=# button_tag t("layout.register_request.approve_selected"), :class => 'approve_registration'
|
||||
=# button_tag t("layout.register_request.reject_selected"), :class => 'reject_registration'
|
||||
.pagination
|
||||
= will_paginate @register_requests
|
||||
:javascript
|
||||
$(function() {
|
||||
var $form = $('form.update_form')
|
||||
var change_update_type = function (type) {
|
||||
$('input#update_type').val(type);
|
||||
};
|
||||
$('#approve_registration').live('click', function(e) {
|
||||
//set update_type to 'approve'
|
||||
change_update_type('approve');
|
||||
$form.submit();
|
||||
});
|
||||
$('#reject_registration').live('click', function(e) {
|
||||
//set update_type to 'reject'
|
||||
change_update_type('reject');
|
||||
$form.submit();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
#block-login.block
|
||||
%h2= title t("layout.register_request.get_token_header")
|
||||
.content.login
|
||||
- if flash.present?
|
||||
.flash
|
||||
- flash.each do |key, value|
|
||||
.message{ :title => key.to_s.humanize, :class => (key == :alert ? "error" : key) }
|
||||
%p= value
|
||||
- form_for(@register_request, :html => { :class => "form login" }) do |f|
|
||||
.group.wat-cf
|
||||
.left
|
||||
= f.label :name, :class => "label right"
|
||||
.right
|
||||
= f.text_field :name, :class => "text_field"
|
||||
.group.wat-cf
|
||||
.left
|
||||
= f.label :email, :class => "label right"
|
||||
.right
|
||||
= f.text_field :email, :class => "text_field"
|
||||
.group.navform.wat-cf
|
||||
.right
|
||||
%button.button{ :type => "submit" }
|
||||
= t("layout.register_request.get_token_button")
|
||||
%span.text_button_padding
|
|
@ -0,0 +1,7 @@
|
|||
%p== Здравствуйте, #{@register_request.name}.
|
||||
|
||||
%p
|
||||
Вы приглашены в проект ABF. Чтобы зарегистрироваться перейдите по
|
||||
= link_to 'ссылке', new_user_registration_url(:invitation_token => @register_request.token)
|
||||
|
||||
%p== Команда поддержки «ROSA Build System»
|
|
@ -3,6 +3,7 @@
|
|||
%ul.wat-cf
|
||||
%li.first.active= link_to t("layout.users.list"), users_path
|
||||
%li= link_to t("layout.users.new"), new_user_path
|
||||
%li= link_to t("layout.users.register_requests"), register_requests_path if can? :read, RegisterRequest
|
||||
.content
|
||||
%h2.title
|
||||
= t("layout.users.list_header")
|
||||
|
|
|
@ -16,6 +16,8 @@ Rosa::Application.configure do
|
|||
|
||||
# Don't care if the mailer can't send
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
config.action_mailer.delivery_method = :smtp # :letter_opener
|
||||
config.action_mailer.smtp_settings = { :host => "localhost", :port => 1025 }
|
||||
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
||||
|
||||
# Print deprecation notices to the Rails logger
|
||||
|
|
|
@ -950,6 +950,7 @@ en:
|
|||
new_user_notification: Registered on project «%{ project_name }»
|
||||
issue_assign_notification: New task assigned
|
||||
new_commit_comment_notification: New comment to commit
|
||||
invite_approve_notification: Invitation to ABF
|
||||
|
||||
project:
|
||||
category_id: Category
|
||||
|
|
|
@ -797,3 +797,4 @@ ru:
|
|||
new_user_notification: Регистрация на проекте «%{ project_name }»
|
||||
issue_assign_notification: Вам назначили задачу
|
||||
new_commit_comment_notification: Новый комментарий к коммиту
|
||||
invite_approve_notification: Приглашение в ABF
|
||||
|
|
|
@ -9,7 +9,16 @@ Rosa::Application.routes.draw do
|
|||
|
||||
resources :users do
|
||||
resources :groups, :only => [:new, :create, :index]
|
||||
get :autocomplete_user_uname, :on => :collection
|
||||
collection do
|
||||
resources :register_requests, :only => [:index, :new, :create, :show_message, :approve, :reject] do
|
||||
get :show_message, :on => :collection
|
||||
put :update, :on => :collection
|
||||
get :approve
|
||||
get :reject
|
||||
end
|
||||
get :autocomplete_user_uname
|
||||
end
|
||||
|
||||
namespace :settings do
|
||||
resource :notifier, :only => [:show, :update]
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
class RemoveOrphanPlatforms < ActiveRecord::Migration
|
||||
def self.up
|
||||
Platform.all.each {|x| x.destroy unless x.owner.present?}
|
||||
end
|
||||
|
||||
def self.down
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
class CreateRegisterRequests < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :register_requests do |t|
|
||||
t.string :name
|
||||
t.string :email
|
||||
t.string :token
|
||||
t.boolean :approved, :default => false
|
||||
t.boolean :rejected, :default => false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :register_requests, [:email], :unique => true, :case_sensitive => false
|
||||
add_index :register_requests, [:token], :unique => true, :case_sensitive => false
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_index :register_requests, [:email]
|
||||
remove_index :register_requests, [:token]
|
||||
drop_table :register_requests
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
class AddMoreFieldsToRegisterRequests < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :register_requests, :interest, :string
|
||||
add_column :register_requests, :more, :text
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :register_requests, :interest
|
||||
remove_column :register_requests, :more
|
||||
end
|
||||
end
|
22
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120131141651) do
|
||||
ActiveRecord::Schema.define(:version => 20120210141153) do
|
||||
|
||||
create_table "arches", :force => true do |t|
|
||||
t.string "name", :null => false
|
||||
|
@ -90,12 +90,12 @@ ActiveRecord::Schema.define(:version => 20120131141651) do
|
|||
end
|
||||
|
||||
create_table "comments", :force => true do |t|
|
||||
t.string "commentable_id"
|
||||
t.string "commentable_type"
|
||||
t.integer "user_id"
|
||||
t.text "body"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.decimal "commentable_id", :precision => 50, :scale => 0
|
||||
end
|
||||
|
||||
create_table "containers", :force => true do |t|
|
||||
|
@ -117,6 +117,7 @@ ActiveRecord::Schema.define(:version => 20120131141651) do
|
|||
t.string "locked_by"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "queue"
|
||||
end
|
||||
|
||||
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
|
||||
|
@ -263,6 +264,21 @@ ActiveRecord::Schema.define(:version => 20120131141651) do
|
|||
add_index "projects", ["category_id"], :name => "index_projects_on_category_id"
|
||||
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true, :case_sensitive => false
|
||||
|
||||
create_table "register_requests", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "email"
|
||||
t.string "token"
|
||||
t.boolean "approved", :default => false
|
||||
t.boolean "rejected", :default => false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "interest"
|
||||
t.text "more"
|
||||
end
|
||||
|
||||
add_index "register_requests", ["email"], :name => "index_register_requests_on_email", :unique => true, :case_sensitive => false
|
||||
add_index "register_requests", ["token"], :name => "index_register_requests_on_token", :unique => true, :case_sensitive => false
|
||||
|
||||
create_table "relations", :force => true do |t|
|
||||
t.integer "object_id"
|
||||
t.string "object_type"
|
||||
|
@ -323,7 +339,6 @@ ActiveRecord::Schema.define(:version => 20120131141651) do
|
|||
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"
|
||||
t.datetime "updated_at"
|
||||
|
@ -331,6 +346,7 @@ ActiveRecord::Schema.define(:version => 20120131141651) do
|
|||
t.string "uname"
|
||||
t.string "role"
|
||||
t.string "language", :default => "en"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.integer "own_projects_count", :default => 0, :null => false
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
module Preregistration
|
||||
module Devise
|
||||
module RegistrationsController
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
alias_method_chain :create, :token
|
||||
alias_method_chain :new, :token
|
||||
end
|
||||
|
||||
def new_with_token
|
||||
if params['invitation_token']
|
||||
req = RegisterRequest.approved.where(:token => params['invitation_token'].strip).first
|
||||
redirect_to new_register_request_path and return unless req
|
||||
|
||||
resource = build_resource({})
|
||||
resource.name = req.name if resource.respond_to? :name
|
||||
resource.email = req.email if resource.respond_to? :email
|
||||
@invitation_token = req.token
|
||||
|
||||
respond_with_navigational(resource){ render_with_scope :new }
|
||||
else
|
||||
redirect_to new_register_request_path
|
||||
end
|
||||
end
|
||||
|
||||
def create_with_token
|
||||
redirect_to new_register_request_path and return unless params['invitation_token']
|
||||
req = RegisterRequest.approved.where(:token => params['invitation_token'].strip).first
|
||||
|
||||
build_resource
|
||||
|
||||
redirect_to new_register_request_path and return unless req and resource.email == req.email
|
||||
|
||||
@invitation_token = req.token
|
||||
if resource.save
|
||||
if resource.active_for_authentication?
|
||||
set_flash_message :notice, :signed_up if is_navigational_format?
|
||||
sign_in(resource_name, resource)
|
||||
respond_with resource, :location => after_sign_up_path_for(resource)
|
||||
else
|
||||
set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
|
||||
expire_session_data_after_sign_in!
|
||||
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
|
||||
end
|
||||
else
|
||||
clean_up_passwords(resource)
|
||||
respond_with_navigational(resource) { render_with_scope :new }
|
||||
end
|
||||
end
|
||||
|
||||
end #RegistrationsController
|
||||
end #Devise
|
||||
end #Preregistration
|
||||
|
||||
Rails.application.config.to_prepare do
|
||||
::Devise::RegistrationsController.send :include, Preregistration::Devise::RegistrationsController
|
||||
end
|
|
@ -0,0 +1,113 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Сборочная среда</title>
|
||||
<script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="styles/prereg.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<!--Top block-->
|
||||
<header>
|
||||
<div class="logo">
|
||||
</div>
|
||||
|
||||
<div class="text">
|
||||
Платформа разработки и управления жизненным циклом дистрибутивов: от исходного кода до ISO-образов
|
||||
</div>
|
||||
|
||||
<div class="both">
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!--Page-->
|
||||
<article>
|
||||
<div class="left">
|
||||
<p>
|
||||
Приветствуем Вас!<br /><br />
|
||||
Вы находитесь на странице размещения заявок на участие в бета-тестировании сборочного сервиса ABF компании РОСА.<br /><br />
|
||||
В первую очередь одобряются заявки от потенциальных майнтейнеров и представителей дистрибутивных команд.<br /><br />
|
||||
Ознакомиться с документацией можно <a href="http://wiki.rosalab.ru/index.php/Сборочная_среда_ABF">здесь</a>.<br /><br />
|
||||
Мы будем рады ответить на Ваши вопросы на <a href="http://forum.rosalab.ru/viewforum.php?f=10">форуме</a> проекта.
|
||||
</p>
|
||||
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>Хочу стать бета-тестером ABF!</h3>
|
||||
|
||||
<form accept-charset="UTF-8" name='invite_form' action="/users/register_requests" id="new_register_request" method="post">
|
||||
<div class="signup-left">
|
||||
Имя, Фамилия
|
||||
</div>
|
||||
<div class="signup-right">
|
||||
<input type="text" id="email" name="register_request[name]" class="registartion-input-signup" onkeydown="buttonCheck();" onClick="this.className='registartion-input-focus';disError(this);" onfocus="if(this.value=='Логин или email'){this.value='';this.className='registartion-input-focus';};" onblur="if(this.value==''){this.value='';this.className='registartion-input-signup';}else{this.className='registartion-input-no-focus';};buttonCheck();" />
|
||||
</div>
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
<div class="signup-left">
|
||||
Электронная почта
|
||||
</div>
|
||||
<div class="signup-right">
|
||||
<input type="text" id="email" name="register_request[email]" class="registartion-input-signup" onkeydown="buttonCheck();" onClick="this.className='registartion-input-focus';disError(this);" onfocus="if(this.value=='Логин или email'){this.value='';this.className='registartion-input-focus';};" onblur="if(this.value==''){this.value='';this.className='registartion-input-signup';}else{this.className='registartion-input-no-focus';};buttonCheck();" />
|
||||
</div>
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
<div class="signup-left">
|
||||
Степень интереса<br>к проекту
|
||||
</div>
|
||||
<div class="signup-right">
|
||||
<select name="register_request[interest]" class="registartion-input-signup">
|
||||
<option>Общеобразовательные цели</option>
|
||||
<option>Хочу стать майнтейнером РОСы</option>
|
||||
<option>Хочу собрать в ABF дистрибутив</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
<div class="signup-left">
|
||||
Также хочу сказать
|
||||
</div>
|
||||
<div class="signup-right">
|
||||
<textarea name="register_request[more]" class="registartion-input-signup" rows="3"></textarea>
|
||||
</div>
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
|
||||
<div class="button">
|
||||
<input class="button" type="submit" value="Отправить">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div style="clear: both;">
|
||||
</div>
|
||||
|
||||
<div class="both">
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</div>
|
||||
<!--Footer-->
|
||||
<footer>
|
||||
<ul>
|
||||
<li>
|
||||
ROSA Лаб. © 2012 <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<img src="pics/flag.png" alt="rosa" /> <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.rosalab.ru/about">О компании</a> <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.rosalab.ru/about/contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,243 @@
|
|||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Tahoma, Arial;
|
||||
color: #565667;
|
||||
background: #1f60a1 url("../pics/bg.png") repeat-x;
|
||||
min-width: 940px;
|
||||
min-height: 300px;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header, section, footer, aside, nav, article, menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type="text"]:focus { outline: none; }
|
||||
|
||||
input[type="password"]:focus { outline: none; }
|
||||
|
||||
input:focus { outline: none; }
|
||||
|
||||
select:focus { outline: none; }
|
||||
|
||||
a img { border: none; }
|
||||
|
||||
.wrap {
|
||||
width: 940px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
min-height: 95%;
|
||||
}
|
||||
|
||||
.both {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
/* Header */
|
||||
|
||||
header div.logo {
|
||||
background: url("../pics/logo.png") no-repeat 50% 100%;
|
||||
height: 89px;
|
||||
width: 233px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding-top: 8%;
|
||||
}
|
||||
|
||||
header div.text {
|
||||
color: #FFF;
|
||||
font-size: 28px;
|
||||
width: 800px;
|
||||
text-align: left;
|
||||
margin-left: 90px;
|
||||
margin-top: 50px;
|
||||
font-family: Arial;
|
||||
text-shadow: 0px 1px 1px #000000;
|
||||
filter: dropshadow(color=#000000, offx=0, offy=1);
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
|
||||
article {
|
||||
width: 760px;
|
||||
height: 305px;
|
||||
background: #1c394c url("../pics/bg-signup.png") repeat-x;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #38658c;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
margin-top: 50px;
|
||||
-webkit-box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
padding-top: 5px;
|
||||
color: #FFF;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
article p{
|
||||
margin: 0;
|
||||
padding: 10px 15px;
|
||||
margin: 0px 0 0px 0;
|
||||
}
|
||||
|
||||
article div.left {
|
||||
float: left;
|
||||
width: 340px;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
margin-top: 0px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
article div.right {
|
||||
float: right;
|
||||
width: 338px;
|
||||
margin-top: 0px;
|
||||
border-left: 2px solid #223e51;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
article div.left a {
|
||||
color: #FFF;
|
||||
/* padding-right: 29px;*/
|
||||
}
|
||||
|
||||
article div.left a.last {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
article div.right p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
article div.all a {
|
||||
color: #FFF;
|
||||
/* padding-right: 29px;*/
|
||||
}
|
||||
|
||||
article div.all p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
article div.all {
|
||||
float: left;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
margin-top: 25px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
|
||||
article div.signup-left {
|
||||
float: left;
|
||||
color: #FFF;
|
||||
font-size: 12px;
|
||||
padding-top: 16px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
article div.signup-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
article div.signup-right input {
|
||||
height: 21px;
|
||||
width: 185px;
|
||||
border: 1px solid #8199a9;
|
||||
border-radius: 2px;
|
||||
font-family: Tahoma;
|
||||
font-size: 12px;
|
||||
/* padding-left: 10px;*/
|
||||
margin-top: 6px;
|
||||
margin-top: 14px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
article div.signup-right textarea, article div.signup-right select {
|
||||
width: 185px;
|
||||
border: 1px solid #8199a9;
|
||||
border-radius: 2px;
|
||||
font-family: Tahoma;
|
||||
font-size: 12px;
|
||||
margin-top: 6px;
|
||||
margin-top: 14px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
article div.signup-right select { width: 190px; }
|
||||
|
||||
article div.button {
|
||||
float: right;
|
||||
margin: 19px 15px 0px 0px;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #125687;
|
||||
background: url("../pics/button-green-normal.png");
|
||||
border-radius: 3px;
|
||||
color: #FFF;
|
||||
font-family: Tahoma;
|
||||
font-size: 12px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-weight: normal;
|
||||
padding: 6px 25px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
height: 27px;
|
||||
width: 106px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.button:hover {
|
||||
background: #1874b6;
|
||||
background: url("../pics/button-green-hover.png");
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.button:active{
|
||||
background: url("../pics/button-green-press.png");
|
||||
}
|
||||
|
||||
a.button:disabled, a.button.disabled {
|
||||
background: #125687;
|
||||
background: url("../pics/button-blue-disabled.png");
|
||||
padding: 5px 15px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
footer {
|
||||
height: 32px;
|
||||
padding-left: 15px;
|
||||
width: 900px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
font-size: 12px;
|
||||
color: #FFF;
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
footer ul li a {
|
||||
font-size: 12px;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Сборочная среда</title>
|
||||
<script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="styles/prereg.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<!--Top block-->
|
||||
<header>
|
||||
<div class="logo">
|
||||
</div>
|
||||
|
||||
<div class="text">
|
||||
Платформа разработки и управления жизненным циклом дистрибутивов: от исходного кода до ISO-образов
|
||||
</div>
|
||||
|
||||
<div class="both">
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!--Page-->
|
||||
<article>
|
||||
<div class="all">
|
||||
<p>
|
||||
<span style="font-size: 28px;">Спасибо!</span><br /><br />
|
||||
Благодарим за интерес к нашему сервису ABF!<br /><br />
|
||||
Приглашение будет выслано вам по указанной электронной почте.<br /><br />
|
||||
Приглашаем Вас на <a href="http://forum.rosalab.ru/viewforum.php?f=10">форум</a> проекта, где мы будем рады ответить на Ваши вопросы и получить Ваши пожелания.<br /><br />
|
||||
Ознакомиться с документацией можно <a href="http://wiki.rosalab.ru/index.php/Сборочная_среда_ABF">здесь</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="both">
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</div>
|
||||
<!--Footer-->
|
||||
<footer>
|
||||
<ul>
|
||||
<li>
|
||||
ROSA Лаб. © 2012 <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<img src="pics/flag.png" alt="rosa" /> <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.rosalab.ru/about">О компании</a> <img src="pics/square.png" alt="_" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.rosalab.ru/about/contacts">Контакты</a>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
# Read about factories at http://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :register_request do
|
||||
name "MyString"
|
||||
email "MyString"
|
||||
token "MyString"
|
||||
approved false
|
||||
end
|
||||
end
|
|
@ -22,6 +22,7 @@ describe CanCan do
|
|||
let(:personal_repository) { Factory(:personal_repository) }
|
||||
let(:open_platform) { Factory(:platform, :visibility => 'open') }
|
||||
let(:hidden_platform) { Factory(:platform, :visibility => 'hidden') }
|
||||
let(:register_request) { Factory(:register_request) }
|
||||
|
||||
before(:each) do
|
||||
stub_rsync_methods
|
||||
|
@ -44,6 +45,10 @@ describe CanCan do
|
|||
it 'should not be able to destroy personal repositories' do
|
||||
@ability.should_not be_able_to(:destroy, personal_repository)
|
||||
end
|
||||
|
||||
it 'should not be able to create new register requests' do
|
||||
@ability.should_not be_able_to(:create, RegisterRequest)
|
||||
end
|
||||
end
|
||||
|
||||
context 'Site guest' do
|
||||
|
@ -69,6 +74,22 @@ describe CanCan do
|
|||
end
|
||||
end
|
||||
|
||||
it 'should be able to create register request' do
|
||||
@ability.should be_able_to(:create, RegisterRequest)
|
||||
end
|
||||
|
||||
it 'should not be able to update register request' do
|
||||
@ability.should_not be_able_to(:update, register_request)
|
||||
end
|
||||
|
||||
it 'should not be able to list register requests' do
|
||||
@ability.should_not be_able_to(:read, register_request)
|
||||
end
|
||||
|
||||
it 'should not be able to destroy register requests' do
|
||||
@ability.should_not be_able_to(:destroy, register_request)
|
||||
end
|
||||
|
||||
it 'should be able to register new user' do
|
||||
@ability.should be_able_to(:create, User)
|
||||
end
|
||||
|
@ -105,6 +126,10 @@ describe CanCan do
|
|||
@ability.should be_able_to(:create, Project)
|
||||
end
|
||||
|
||||
it "should not be able to manage register requests" do
|
||||
@ability.should_not be_able_to(:manage, RegisterRequest)
|
||||
end
|
||||
|
||||
context "private users relations" do
|
||||
before(:each) do
|
||||
@private_user = Factory(:private_user)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe RegisterRequest do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|