[issue #133] Merge branch 'master' into 133-editing_from_web

Conflicts:
	db/schema.rb
This commit is contained in:
George Vinogradov 2012-02-13 21:48:40 +04:00
commit 99c314fb11
42 changed files with 802 additions and 19 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -68,7 +68,7 @@ class Project < ActiveRecord::Base
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -1,5 +1,5 @@
= 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}"

View File

@ -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 &nbsp;
%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();
});
});

View File

@ -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

View File

@ -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»

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -797,3 +797,4 @@ ru:
new_user_notification: Регистрация на проекте «%{ project_name }»
issue_assign_notification: Вам назначили задачу
new_commit_comment_notification: Новый комментарий к коммиту
invite_approve_notification: Приглашение в ABF

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

113
public/invite.html Normal file
View File

@ -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>

BIN
public/pics/bg-signup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
public/pics/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
public/pics/flag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
public/pics/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
public/pics/square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

243
public/styles/prereg.css Normal file
View File

@ -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;
}

59
public/thanks.html Normal file
View File

@ -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>

View File

@ -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

View File

@ -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)

View File

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