Merge branch 'master' into 123-activity-feed
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
|
||||
|
|
36
Gemfile.lock
|
@ -54,14 +54,14 @@ GEM
|
|||
activerecord (>= 2.2.2)
|
||||
arel (2.0.10)
|
||||
bcrypt-ruby (3.0.1)
|
||||
bluepill (0.0.52)
|
||||
bluepill (0.0.55)
|
||||
activesupport (>= 3.0.0)
|
||||
daemons (~> 1.1.0)
|
||||
daemons (~> 1.1.4)
|
||||
i18n (>= 0.5.0)
|
||||
state_machine (~> 1.1.0)
|
||||
builder (2.1.2)
|
||||
cancan (1.6.7)
|
||||
cape (1.2.0)
|
||||
cape (1.4.0)
|
||||
capistrano (2.9.0)
|
||||
highline
|
||||
net-scp (>= 1.0.0)
|
||||
|
@ -74,7 +74,7 @@ GEM
|
|||
chronic (0.6.7)
|
||||
cocaine (0.2.1)
|
||||
creole (0.4.2)
|
||||
daemons (1.1.6)
|
||||
daemons (1.1.8)
|
||||
delayed_job (2.1.4)
|
||||
activesupport (~> 3.0)
|
||||
daemons
|
||||
|
@ -85,13 +85,14 @@ 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
|
||||
factory_girl_rails (1.4.0)
|
||||
factory_girl (~> 2.3.0)
|
||||
railties (>= 3.0.0)
|
||||
github-markup (0.7.0)
|
||||
github-markup (0.7.1)
|
||||
gollum (1.3.1)
|
||||
albino (~> 1.3.2)
|
||||
github-markup (>= 0.4.0, < 1.0.0)
|
||||
|
@ -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)
|
||||
|
@ -141,7 +152,7 @@ GEM
|
|||
omniauth (~> 1.0)
|
||||
rack-openid (~> 1.3.1)
|
||||
orm_adapter (0.0.6)
|
||||
paperclip (2.5.2)
|
||||
paperclip (2.6.0)
|
||||
activerecord (>= 2.3.0)
|
||||
activesupport (>= 2.3.2)
|
||||
cocaine (>= 0.0.2)
|
||||
|
@ -168,7 +179,7 @@ GEM
|
|||
rails-xmlrpc (0.3.6)
|
||||
rails3-generators (0.17.4)
|
||||
railties (>= 3.0.0)
|
||||
rails3-jquery-autocomplete (1.0.5)
|
||||
rails3-jquery-autocomplete (1.0.6)
|
||||
rails (~> 3.0)
|
||||
railties (3.0.11)
|
||||
actionpack (= 3.0.11)
|
||||
|
@ -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
|
||||
|
|
|
@ -6,7 +6,8 @@ class CollaboratorsController < ApplicationController
|
|||
before_filter :find_users
|
||||
before_filter :find_groups
|
||||
|
||||
load_and_authorize_resource :project
|
||||
load_resource :project
|
||||
before_filter :authorize_collaborators
|
||||
|
||||
def index
|
||||
redirect_to edit_project_collaborators_path(@project)
|
||||
|
@ -130,4 +131,8 @@ class CollaboratorsController < ApplicationController
|
|||
def find_groups
|
||||
@groups = @project.groups#Group.all
|
||||
end
|
||||
|
||||
def authorize_collaborators
|
||||
authorize! :update, @project
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ class Git::BlobsController < Git::BaseController
|
|||
before_filter :set_commit_hash
|
||||
|
||||
def show
|
||||
redirect_to project_repo_path(@project) and return unless @blob.present?
|
||||
if params[:raw]
|
||||
image_url = Rails.root.to_s + "/" + @path
|
||||
|
||||
|
@ -16,11 +17,34 @@ class Git::BlobsController < Git::BaseController
|
|||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
redirect_to project_repo_path(@project) and return unless @blob.present?
|
||||
authorize! :write, @project
|
||||
end
|
||||
|
||||
def update
|
||||
redirect_to project_repo_path(@project) and return unless @blob.present?
|
||||
authorize! :write, @project
|
||||
# Here might be callbacks for notification purposes:
|
||||
# @git_repository.after_update_file do |repo, sha|
|
||||
# end
|
||||
|
||||
res = @git_repository.update_file(params[:path], params[:content],
|
||||
:message => params[:message], :actor => current_user, :head => @treeish)
|
||||
if res
|
||||
flash[:notice] = t("flash.blob.successfully_updated", :name => params[:path].encode_to_default)
|
||||
else
|
||||
flash[:notice] = t("flash.blob.updating_error", :name => params[:path].encode_to_default)
|
||||
end
|
||||
redirect_to :action => :show
|
||||
end
|
||||
|
||||
def blame
|
||||
@blame = Grit::Blob.blame(@git_repository.repo, @commit.try(:id), @path)
|
||||
end
|
||||
|
||||
def raw
|
||||
redirect_to project_repo_path(@project) and return unless @blob.present?
|
||||
headers["Content-Disposition"] = %[attachment;filename="#{@blob.name}"]
|
||||
render :text => @blob.data, :content_type => @blob.mime_type
|
||||
end
|
||||
|
@ -28,7 +52,8 @@ class Git::BlobsController < Git::BaseController
|
|||
protected
|
||||
def set_path_blob
|
||||
@path = params[:path]
|
||||
@blob = @tree / @path.encode_to_default
|
||||
@path.force_encoding(Encoding::ASCII_8BIT)
|
||||
@blob = @tree / @path
|
||||
end
|
||||
|
||||
def set_commit_hash
|
||||
|
|
|
@ -3,6 +3,7 @@ class Git::TreesController < Git::BaseController
|
|||
|
||||
def show
|
||||
@path = params[:path]
|
||||
@path.force_encoding(Encoding::ASCII_8BIT) if @path
|
||||
|
||||
@tree = @git_repository.tree(@treeish)
|
||||
|
||||
|
|
|
@ -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
|
|
@ -48,12 +48,10 @@ class WikiController < ApplicationController
|
|||
@name = CGI.unescape(params[:id])
|
||||
@page = @wiki.page(@name)
|
||||
name = params[:rename] || @name
|
||||
committer = Gollum::Committer.new(@wiki, commit)
|
||||
commit_arg = {:committer => committer}
|
||||
|
||||
update_wiki_page(@wiki, @page, params[:content], commit_arg, name, params[:format])
|
||||
update_wiki_page(@wiki, @page.footer, params[:footer], commit_arg) if params[:footer]
|
||||
update_wiki_page(@wiki, @page.sidebar, params[:sidebar], commit_arg) if params[:sidebar]
|
||||
update_wiki_page(@wiki, @page, params[:content], {:committer => committer}, name, params[:format])
|
||||
update_wiki_page(@wiki, @page.footer, params[:footer], {:committer => committer}) if params[:footer]
|
||||
update_wiki_page(@wiki, @page.sidebar, params[:sidebar], {:committer => committer}) if params[:sidebar]
|
||||
|
||||
committer.commit
|
||||
|
||||
|
@ -68,9 +66,8 @@ class WikiController < ApplicationController
|
|||
def create
|
||||
@name = CGI.unescape(params['page'])
|
||||
format = params['format'].intern
|
||||
|
||||
begin
|
||||
@wiki.write_page(@name, format, params['content'] || '', commit)
|
||||
@wiki.write_page(@name, format, params['content'] || '', {:committer => committer}).commit
|
||||
redirect_to project_wiki_path(@project, CGI.escape(@name))
|
||||
rescue Gollum::DuplicatePageError => e
|
||||
flash[:error] = t("flash.wiki.duplicate_page", :name => @name)
|
||||
|
@ -82,7 +79,7 @@ class WikiController < ApplicationController
|
|||
@name = CGI.unescape(params[:id])
|
||||
page = @wiki.page(@name)
|
||||
if page
|
||||
@wiki.delete_page(page, commit.merge(:message => 'Page removed'))
|
||||
@wiki.delete_page(page, {:committer => committer}).commit
|
||||
flash[:notice] = t("flash.wiki.page_successfully_removed")
|
||||
else
|
||||
flash[:notice] = t("flash.wiki.page_not_found", :name => params[:id])
|
||||
|
@ -145,7 +142,7 @@ class WikiController < ApplicationController
|
|||
sha1 = params[:sha1]
|
||||
sha2 = params[:sha2]
|
||||
|
||||
if @wiki.revert_page(@page, sha1, sha2, commit)
|
||||
if @wiki.revert_page(@page, sha1, sha2, {:committer => committer}).commit
|
||||
flash[:notice] = t("flash.wiki.revert_success")
|
||||
redirect_to project_wiki_path(@project, CGI.escape(@name))
|
||||
else
|
||||
|
@ -165,7 +162,7 @@ class WikiController < ApplicationController
|
|||
def revert_wiki
|
||||
sha1 = params[:sha1]
|
||||
sha2 = params[:sha2]
|
||||
if @wiki.revert_commit(sha1, sha2, commit)
|
||||
if @wiki.revert_commit(sha1, sha2, {:committer => committer}).commit
|
||||
flash[:notice] = t("flash.wiki.revert_success")
|
||||
redirect_to project_wiki_index_path(@project)
|
||||
else
|
||||
|
@ -233,11 +230,11 @@ class WikiController < ApplicationController
|
|||
if params['message'] and !params['message'].empty?
|
||||
msg = params['message']
|
||||
else
|
||||
# msg = "#{!!@wiki.page(@name) ? 'Updated page' : 'Created page'} #{@name}"
|
||||
msg = case action_name.to_s
|
||||
when 'create' then "Created page #{@name.to_s}"
|
||||
when 'update' then "Updated page #{@name.to_s}"
|
||||
when 'revert' then "Reverted page #{@name.to_s}"
|
||||
when 'create' then "Created page #{@name.to_s}"
|
||||
when 'update' then "Updated page #{@name.to_s}"
|
||||
when 'destroy' then "Removed page #{@name.to_s}"
|
||||
when 'revert' then "Reverted page #{@name.to_s}"
|
||||
when 'revert_wiki' then "Reverted wiki"
|
||||
end
|
||||
msg += " (#{params['format']})" if params['format']
|
||||
|
@ -246,8 +243,13 @@ class WikiController < ApplicationController
|
|||
{ :message => msg }
|
||||
end
|
||||
|
||||
def commit
|
||||
commit_message.merge({:name => current_user.uname, :email => current_user.email})
|
||||
def committer
|
||||
p = commit_message.merge({:name => current_user.uname, :email => current_user.email})
|
||||
@committer ||= Gollum::Committer.new(@wiki, p)
|
||||
# @committer.after_commit do |committer, sha1|
|
||||
# here goes callback for notification
|
||||
# end
|
||||
@committer
|
||||
end
|
||||
|
||||
def show_or_create_page
|
||||
|
@ -258,20 +260,19 @@ class WikiController < ApplicationController
|
|||
elsif file = @wiki.file(@name)
|
||||
render :text => file.raw_data, :content_type => file.mime_type
|
||||
elsif can? :write, @project
|
||||
# @name = CGI.escape(@name)
|
||||
@new = true
|
||||
render :new
|
||||
else
|
||||
redirect_to forbidden_path
|
||||
redirect_to :action => :index #forbidden_path
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_read_actions
|
||||
redirect_to forbidden_path and return if cannot? :read, @project
|
||||
authorize! :read, @project
|
||||
end
|
||||
|
||||
def authorize_write_actions
|
||||
redirect_to forbidden_path and return if cannot? :write, @project
|
||||
authorize! :write, @project
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ module DiffHelper
|
|||
res += "</tbody>"
|
||||
res += "</table>"
|
||||
|
||||
res.html_safe.force_encoding(Encoding.default_internal || Encoding::UTF_8)
|
||||
res.html_safe.encode_to_default
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -29,6 +29,14 @@ module GitHelper
|
|||
res.encode_to_default.html_safe
|
||||
end
|
||||
|
||||
def blob_file_path
|
||||
if @commit_hash.present?
|
||||
blob_commit_path(@project, @commit_hash, @path)
|
||||
else
|
||||
blob_path(@project, @treeish, @path)
|
||||
end
|
||||
end
|
||||
|
||||
def render_line_numbers(n)
|
||||
res = ""
|
||||
1.upto(n) {|i| res += "<span>#{i}</span>\n" }
|
||||
|
|
|
@ -86,7 +86,7 @@ module WikiHelper
|
|||
end
|
||||
|
||||
def author
|
||||
@page.version.author.name.force_encoding(Encoding.default_internal || Encoding::UTF_8)
|
||||
@page.version.author.name.encode_to_default
|
||||
end
|
||||
|
||||
def author_email
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
class Git::Repository
|
||||
delegate :commits, :commit, :tree, :tags, :heads, :commit_count, :log, :branches, :to => :repo
|
||||
|
||||
attr_accessor :path, :name
|
||||
attr_accessor :path, :name, :repo, :last_actor
|
||||
|
||||
def initialize(path)
|
||||
@path = path
|
||||
@update_callbacks = []
|
||||
end
|
||||
|
||||
def master
|
||||
|
@ -20,6 +21,65 @@ class Git::Repository
|
|||
@repo ||= Grit::Repo.new(path)
|
||||
end
|
||||
|
||||
# Adds a callback to be fired after update file.
|
||||
#
|
||||
# block - A block that expects this Git::Repository instance and the created
|
||||
# commit's SHA1 as the arguments.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# after_update_file do |repo, sha|
|
||||
# # callback body
|
||||
# end
|
||||
#
|
||||
# Returns nothing.
|
||||
def after_update_file(&block)
|
||||
@update_callbacks << block
|
||||
end
|
||||
|
||||
# Writes file to repo and runs 'after_update_file' callbacks
|
||||
#
|
||||
# path - path to file in repository
|
||||
# data - new content of file
|
||||
# options - an optional Hash of options
|
||||
# :head - branch name to write this commit to
|
||||
# (Default: 'master')
|
||||
# :actor - author of this commit. (See Git::Repository#get_actor)
|
||||
# (Default: nil)
|
||||
# :message - commit message
|
||||
# (Default: "Updated file <filename>")
|
||||
#
|
||||
# Returns commits sha if committing was successful and false otherwise
|
||||
def update_file(path, data, options = {})
|
||||
path.force_encoding(Encoding::ASCII_8BIT) # some magic
|
||||
|
||||
head = options[:head].to_s || 'master'
|
||||
actor = get_actor(options[:actor])
|
||||
filename = File.split(path).last
|
||||
message = options[:message]
|
||||
message = "Updated file #{filename}" if message.nil? or message.empty?
|
||||
|
||||
# can not write to unexisted branch
|
||||
return false if branches.select{|b| b.name == head}.size != 1
|
||||
|
||||
parent = commits(head).first
|
||||
|
||||
index = repo.index
|
||||
index.read_tree(parent.tree.id)
|
||||
|
||||
# can not create new file
|
||||
return false if (index.current_tree / path).nil?
|
||||
|
||||
index.add(path, data)
|
||||
sha = index.commit(message, :parents => [parent], :actor => actor,
|
||||
:last_tree => parent.tree.id, :head => head)
|
||||
# call all defined callbacks
|
||||
@update_callbacks.each do |cb|
|
||||
cb.call(self, sha)
|
||||
end
|
||||
sha
|
||||
end
|
||||
|
||||
def self.create(path)
|
||||
repo = Grit::Repo.init_bare(path)
|
||||
repo.enable_daemon_serve
|
||||
|
@ -38,4 +98,35 @@ class Git::Repository
|
|||
[commits(treeish, options[:per_page], skip), options[:page], last_page]
|
||||
end
|
||||
|
||||
# Pretty object inspection
|
||||
def inspect
|
||||
%Q{#<Git::Repository "#{@path}">}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Creates new Grit::Actor instance
|
||||
#
|
||||
# Might be:
|
||||
# * A Hash containing :name and :email
|
||||
# * An instance of Grit::Actor
|
||||
# * A String like "John Doe <j.doe@example.com>
|
||||
# * Any object that responds to `name` and `email` methods
|
||||
def get_actor(actor = nil)
|
||||
@last_actor = case actor.class.to_s
|
||||
when 'Grit::Actor' then options[:actor]
|
||||
when 'Hash' then Grit::Actor.new(actor[:name], actor[:email])
|
||||
when 'String' then Grit::Actor.from_stirng(actor)
|
||||
else begin
|
||||
if actor.respond_to?(:name) and actor.respond_to?(:email)
|
||||
Grit::Actor.new(actor.name, actor.email)
|
||||
else
|
||||
config = Grit::Config.new(repo)
|
||||
Grit::Actor.new(config['user.name'], config['user.email'])
|
||||
end
|
||||
end
|
||||
end
|
||||
@last_actor
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -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,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}"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#gollum-editor.edit{:'data-escaped-name' => @path.encode_to_default}
|
||||
= form_tag blob_file_path, :name => 'blob-editor', :method => :put do
|
||||
%fieldset#gollum-editor-fields
|
||||
|
||||
= text_area_tag :content, @blob.data.encode_to_default, :id => "gollum-editor-body"
|
||||
|
||||
#gollum-editor-edit-summary.singleline
|
||||
= label_tag :message, t("layout.wiki.edit_commit_message"), :class => "jaws"
|
||||
= text_field_tag :message, t("layout.wiki.commit_message_placeholder"), :id => "editor-commit-message-field"
|
||||
|
||||
%span.jaws
|
||||
%br
|
||||
|
||||
= submit_tag t("layout.wiki.save_button"), :id => "gollum-editor-submit", :title => t("layout.wiki.save_changes")
|
||||
= link_to t("layout.cancel"), blob_file_path, :class => 'minibutton', :id => 'gollum-editor-preview'
|
||||
|
||||
:javascript
|
||||
$(function() {
|
||||
$.BlobEditor();
|
||||
});
|
||||
|
||||
- content_for :javascripts do
|
||||
= javascript_include_tag 'gollum/gollum.placeholder.js', 'blob.editor.js'
|
||||
|
||||
- content_for :stylesheets do
|
||||
= stylesheet_link_tag 'gollum/editor.css'
|
|
@ -0,0 +1,20 @@
|
|||
.block
|
||||
= render :partial => "git/shared/navigation"
|
||||
|
||||
= render :partial => "git/shared/info"
|
||||
|
||||
- if @commit
|
||||
.block
|
||||
.content
|
||||
.inner
|
||||
= render :partial => "git/commits/commits", :object => [@commit]
|
||||
|
||||
.block
|
||||
.content
|
||||
.inner
|
||||
%h3 #{render_path} (#{@blob.mime_type})
|
||||
|
||||
= render :partial => 'editor'
|
||||
|
||||
- content_for :sidebar, render(:partial => 'git/shared/sidebar')
|
||||
|
|
@ -19,9 +19,14 @@
|
|||
.size #{(@blob.size / 1024.0).round(3)} Kb
|
||||
.buttons
|
||||
- if @commit_hash
|
||||
#{link_to "Raw", raw_commit_path(@project, @commit_hash, @path)} #{link_to "Blame", blame_commit_path(@project, @commit_hash, @path)} #{link_to "History", commits_path(@project, @treeish, @path)}
|
||||
#{link_to "Raw", raw_commit_path(@project, @commit_hash, @path)}
|
||||
#{link_to "Blame", blame_commit_path(@project, @commit_hash, @path)}
|
||||
#{link_to "History", commits_path(@project, @treeish, @path)}
|
||||
- else
|
||||
#{link_to "Raw", raw_path(@project, @treeish, @path)} #{link_to "Blame", blame_path(@project, @treeish, @path)} #{link_to "History", commits_path(@project, @treeish, @path)}
|
||||
#{link_to "Edit", edit_blob_path(@project, @treeish, @path) if choose_render_way(@blob) == :text and can? :write, @project}
|
||||
#{link_to "Raw", raw_path(@project, @treeish, @path)}
|
||||
#{link_to "Blame", blame_path(@project, @treeish, @path)}
|
||||
#{link_to "History", commits_path(@project, @treeish, @path)}
|
||||
.clear
|
||||
- case choose_render_way(@blob)
|
||||
- when :image
|
||||
|
|
|
@ -36,10 +36,13 @@
|
|||
- else
|
||||
= image_tag("git/icons/folder_16.png")
|
||||
%td.tree_element
|
||||
- entry_path = File.join([@path.present? ? @path.encode_to_default : nil, entry.name.encode_to_default].compact)
|
||||
- if entry.is_a?(Grit::Blob)
|
||||
= link_to entry.name.encode_to_default, blob_path(@project, @treeish, File.join([@path, entry.name.encode_to_default].compact))
|
||||
= link_to entry.name.encode_to_default,
|
||||
blob_path(@project, @treeish.encode_to_default, entry_path)
|
||||
- else
|
||||
= link_to "#{entry.name.encode_to_default}/", tree_path(@project, @treeish, File.join([@path, entry.name.encode_to_default].compact))
|
||||
= link_to "#{entry.name.encode_to_default}/",
|
||||
tree_path(@project, @treeish.encode_to_default, entry_path)
|
||||
%td==
|
||||
%td.last==
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
%li= link_to t("layout.projects.new"), new_project_path
|
||||
%li= link_to t("layout.projects.show"), project_path(@project)
|
||||
%li.active= link_to t("layout.git.repositories.source"), project_repo_path(@project)
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
- if can? :write, @project
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
|
||||
%ul#git_submenu.sub-wat-cf.wat-cf
|
||||
%li= link_to t("layout.git.repositories.commits"), commits_path(@project, :treeish => @treeish)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-29164163-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
|
@ -57,3 +57,4 @@
|
|||
#sidebar
|
||||
= yield :sidebar
|
||||
|
||||
= render 'layouts/counters' unless current_user.try(:admin?)
|
||||
|
|
|
@ -12,3 +12,5 @@
|
|||
#box
|
||||
= render :partial => "layouts/flashes"
|
||||
= yield
|
||||
|
||||
= render 'layouts/counters' unless current_user.try(:admin?)
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
%li= link_to t("layout.projects.new"), new_project_path
|
||||
%li.active= link_to t("layout.projects.show"), project_path(@project)
|
||||
%li= link_to t("layout.git.repositories.source"), project_repo_path(@project)
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
- if can? :write, @project
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
%li= link_to t("layout.projects.issues"), project_issues_path(@project)
|
||||
- if @project.has_wiki
|
||||
%li= link_to t("layout.projects.wiki"), project_wiki_index_path(@project)
|
||||
|
|
|
@ -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,13 +16,13 @@
|
|||
- user = User.where(:email => v.author.email).first
|
||||
= link_to user_path_by_user(user) do
|
||||
%img{:src => gravatar_url(v.author.email),
|
||||
:alt => "avatar: #{v.author.name.force_encoding(Encoding.default_internal || Encoding::UTF_8)}",
|
||||
:alt => "avatar: #{v.author.name.encode_to_default}",
|
||||
:class => "mini-gravatar"}
|
||||
%span.username= user.present? ? user.uname : v.author.name
|
||||
%span.username= user.present? ? user.uname : v.author.name.encode_to_default
|
||||
%td.commit-name
|
||||
%span.time-elapsed= "#{l v.committed_date.to_date, :format => :long}:"
|
||||
|
||||
= v.message.force_encoding(Encoding.default_internal)
|
||||
= v.message.encode_to_default
|
||||
- if @name
|
||||
= raw "[#{link_to v.id[0..6], versioned_project_wiki_path(@project, escaped_name, v.id), :title => t("layout.wiki.view_commit")}]"
|
||||
- else
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
%li= link_to t("layout.projects.new"), new_project_path
|
||||
%li= link_to t("layout.projects.show"), project_path(@project)
|
||||
%li= link_to t("layout.git.repositories.source"), project_repo_path(@project)
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
- if can? :write, @project
|
||||
%li= link_to t("layout.projects.build"), new_project_build_list_path(@project)
|
||||
%li= link_to t("layout.projects.issues"), project_issues_path(@project)
|
||||
%li.active= link_to t("layout.projects.wiki"), project_wiki_index_path(@project)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -695,6 +695,10 @@ en:
|
|||
revert_success: Changes successfully reverted
|
||||
patch_does_not_apply: Patch does not apply
|
||||
|
||||
blob:
|
||||
successfully_updated: File '%{name}' successfully updated
|
||||
updating_error: Error updating file '%{name}'
|
||||
|
||||
attributes:
|
||||
password: Password
|
||||
password_confirmation: Confirmation
|
||||
|
@ -949,6 +953,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
|
||||
|
|
|
@ -552,6 +552,10 @@ ru:
|
|||
revert_success: Изменения успешно откачены
|
||||
patch_does_not_apply: Не удалось откатить изменения
|
||||
|
||||
blob:
|
||||
successfully_updated: Файл '%{name}' успешно обновлен
|
||||
updating_error: Ошибка обновления файла '%{name}'
|
||||
|
||||
attributes:
|
||||
password: Пароль
|
||||
password_confirmation: Подтверждение
|
||||
|
@ -816,3 +820,4 @@ ru:
|
|||
title: Здравствуйте, %{user_name}.
|
||||
content: Вам была назначена задача %{issue_link}
|
||||
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
|
||||
|
@ -181,12 +190,18 @@ Rosa::Application.routes.draw do
|
|||
match '/projects/:project_id/git/commit/:commit_id/comments/:id(.:format)', :controller => "comments", :action => :update, :as => :project_commit_comment, :via => :put
|
||||
match '/projects/:project_id/git/commit/:commit_id/comments/:id(.:format)', :controller => "comments", :action => :destroy, :via => :delete
|
||||
match '/projects/:project_id/git/commit/:commit_id/comments(.:format)', :controller => "comments", :action => :create, :as => :project_commit_comments, :via => :post
|
||||
|
||||
# Commits subscribe
|
||||
match '/projects/:project_id/git/commit/:commit_id/subscribe', :controller => "commit_subscribes", :action => :create, :defaults => { :format => :html }, :as => :subscribe_commit, :via => :post
|
||||
match '/projects/:project_id/git/commit/:commit_id/unsubscribe', :controller => "commit_subscribes", :action => :destroy, :defaults => { :format => :html }, :as => :unsubscribe_commit, :via => :delete
|
||||
|
||||
# Editing files
|
||||
match '/projects/:project_id/git/blob/:treeish/*path/edit', :controller => "git/blobs", :action => :edit, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :edit_blob, :via => :get
|
||||
match '/projects/:project_id/git/blob/:treeish/*path', :controller => "git/blobs", :action => :update, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :via => :put
|
||||
|
||||
# Blobs
|
||||
match '/projects/:project_id/git/blob/:treeish/*path', :controller => "git/blobs", :action => :show, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :blob
|
||||
match '/projects/:project_id/git/commit/blob/:commit_hash/*path', :controller => "git/blobs", :action => :show, :project_name => /[0-9a-zA-Z_.\-]*/, :as => :blob_commit
|
||||
match '/projects/:project_id/git/blob/:treeish/*path', :controller => "git/blobs", :action => :show, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :blob, :via => :get
|
||||
match '/projects/:project_id/git/commit/blob/:commit_hash/*path', :controller => "git/blobs", :action => :show, :project_id => /[0-9a-zA-Z_.\-]*/, :as => :blob_commit, :via => :get
|
||||
|
||||
# Blame
|
||||
match '/projects/:project_id/git/blame/:treeish/*path', :controller => "git/blobs", :action => :blame, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :blame
|
||||
|
|
|
@ -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
|
33
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120131124517) do
|
||||
ActiveRecord::Schema.define(:version => 20120210141153) do
|
||||
|
||||
create_table "activity_feeds", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
|
@ -98,12 +98,12 @@ ActiveRecord::Schema.define(:version => 20120131124517) 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|
|
||||
|
@ -125,6 +125,7 @@ ActiveRecord::Schema.define(:version => 20120131124517) 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"
|
||||
|
@ -261,16 +262,31 @@ ActiveRecord::Schema.define(:version => 20120131124517) do
|
|||
t.text "description"
|
||||
t.string "ancestry"
|
||||
t.boolean "has_issues", :default => true
|
||||
t.boolean "has_wiki", :default => false
|
||||
t.string "srpm_file_name"
|
||||
t.string "srpm_content_type"
|
||||
t.integer "srpm_file_size"
|
||||
t.datetime "srpm_updated_at"
|
||||
t.boolean "has_wiki", :default => false
|
||||
end
|
||||
|
||||
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"
|
||||
|
@ -328,19 +344,18 @@ ActiveRecord::Schema.define(:version => 20120131124517) do
|
|||
|
||||
create_table "users", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :limit => 128, :default => "", :null => false
|
||||
t.string "password_salt", :default => "", :null => false
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :limit => 128, :default => "", :null => false
|
||||
t.string "reset_password_token"
|
||||
t.string "remember_token"
|
||||
t.datetime "remember_created_at"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.text "ssh_key"
|
||||
t.string "uname"
|
||||
t.string "role"
|
||||
t.string "language", :default => "en"
|
||||
t.integer "own_projects_count", :default => 0, :null => false
|
||||
t.string "language", :default => "en"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.integer "own_projects_count", :default => 0, :null => false
|
||||
end
|
||||
|
||||
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
module Gollum
|
||||
class Page
|
||||
alias_method :native_gollum_name, :name
|
||||
|
||||
def name
|
||||
native_gollum_name.force_encoding(Encoding.default_internal || Encoding::UTF_8)
|
||||
def name_with_encoding
|
||||
name_without_encoding.encode_to_default
|
||||
end
|
||||
|
||||
alias_method_chain :name, :encoding
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,26 +2,90 @@
|
|||
module Gollum
|
||||
class Wiki
|
||||
|
||||
alias_method :native_gollum_page, :page
|
||||
alias_method :native_gollum_file, :file
|
||||
alias_method :native_gollum_write_page, :write_page
|
||||
alias_method :native_gollum_update_page, :update_page
|
||||
|
||||
def page(name, version = @ref)
|
||||
native_gollum_page(force_grit_encoding(name), version)
|
||||
def page_with_forced_encoding(name, version = @ref)
|
||||
page_without_forced_encoding(force_grit_encoding(name), version)
|
||||
end
|
||||
alias_method_chain :page, :forced_encoding
|
||||
|
||||
def file(name, version = @ref)
|
||||
native_gollum_file(force_grit_encoding(name), version)
|
||||
def file_with_forced_encoding(name, version = @ref)
|
||||
file_without_forced_encoding(force_grit_encoding(name), version)
|
||||
end
|
||||
alias_method_chain :file, :forced_encoding
|
||||
|
||||
def write_page(name, format, data, commit = {})
|
||||
native_gollum_write_page(force_grit_encoding(name), format, data, commit)
|
||||
def write_page_with_forced_encoding(name, format, data, commit = {})
|
||||
write_page_without_forced_encoding(force_grit_encoding(name), format, data, commit)
|
||||
end
|
||||
alias_method_chain :write_page, :forced_encoding
|
||||
|
||||
def update_page(page, name, format, data, commit = {})
|
||||
native_gollum_update_page(page, force_grit_encoding(name), format, data, commit)
|
||||
def update_page_with_forced_encoding(page, name, format, data, commit = {})
|
||||
update_page_without_forced_encoding(page, force_grit_encoding(name), format, data, commit)
|
||||
end
|
||||
alias_method_chain :update_page, :forced_encoding
|
||||
|
||||
# Public: Applies a reverse diff for a given page. If only 1 SHA is given,
|
||||
# the reverse diff will be taken from its parent (^SHA...SHA). If two SHAs
|
||||
# are given, the reverse diff is taken from SHA1...SHA2.
|
||||
#
|
||||
# page - The Gollum::Page to delete.
|
||||
# sha1 - String SHA1 of the earlier parent if two SHAs are given,
|
||||
# or the child.
|
||||
# sha2 - Optional String SHA1 of the child.
|
||||
# commit - The commit Hash details:
|
||||
# :message - The String commit message.
|
||||
# :name - The String author full name.
|
||||
# :email - The String email address.
|
||||
# :parent - Optional Grit::Commit parent to this update.
|
||||
#
|
||||
# Returns a String SHA1 of the new commit, or nil if the reverse diff does
|
||||
# not apply.
|
||||
def revert_page_with_committer(page, sha1, sha2 = nil, commit = {})
|
||||
if sha2.is_a?(Hash)
|
||||
commit = sha2
|
||||
sha2 = nil
|
||||
end
|
||||
|
||||
multi_commit = false
|
||||
|
||||
patch = full_reverse_diff_for(page, sha1, sha2)
|
||||
committer = if obj = commit[:committer]
|
||||
multi_commit = true
|
||||
obj
|
||||
else
|
||||
Committer.new(self, commit)
|
||||
end
|
||||
parent = committer.parents[0]
|
||||
committer.options[:tree] = @repo.git.apply_patch(parent.sha, patch)
|
||||
return false unless committer.options[:tree]
|
||||
committer.after_commit do |index, sha|
|
||||
@access.refresh
|
||||
|
||||
files = []
|
||||
if page
|
||||
files << [page.path, page.name, page.format]
|
||||
else
|
||||
# Grit::Diff can't parse reverse diffs.... yet
|
||||
patch.each_line do |line|
|
||||
if line =~ %r{^diff --git b/.+? a/(.+)$}
|
||||
path = $1
|
||||
ext = ::File.extname(path)
|
||||
name = ::File.basename(path, ext)
|
||||
if format = ::Gollum::Page.format_for(ext)
|
||||
files << [path, name, format]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
files.each do |(path, name, format)|
|
||||
dir = ::File.dirname(path)
|
||||
dir = '' if dir == '.'
|
||||
index.update_working_dir(dir, name, format)
|
||||
end
|
||||
end
|
||||
|
||||
multi_commit ? committer : committer.commit
|
||||
end
|
||||
alias_method_chain :revert_page, :committer
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -2,12 +2,8 @@
|
|||
module Grit
|
||||
class Repo
|
||||
|
||||
alias_method :native_grit_diff, :diff
|
||||
|
||||
def diff(a, b, *paths)
|
||||
diff = self.git.native('diff', {}, a, b, '--', *paths).force_encoding(Encoding.default_internal || Encoding::UTF_8)
|
||||
Grit.log 'in grit'
|
||||
Grit.log diff
|
||||
def diff_with_encoding(a, b, *paths)
|
||||
diff = self.git.native('diff', {}, a, b, '--', *paths).encode_to_default
|
||||
if diff =~ /diff --git "{0,1}a/
|
||||
diff = diff.sub(/.*?(diff --git "{0,1}a)/m, '\1')
|
||||
else
|
||||
|
@ -15,6 +11,7 @@ module Grit
|
|||
end
|
||||
Diff.list_from_string(self, diff)
|
||||
end
|
||||
alias_method_chain :diff, :encoding
|
||||
|
||||
end
|
||||
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,126 @@
|
|||
<!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>
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-29164163-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
(function($) {
|
||||
$.BlobEditor = function() {
|
||||
$.BlobEditor.Placeholder.add($('#gollum-editor-edit-summary input'));
|
||||
$('#gollum-editor form[name="blob-editor"]').submit(function( e ) {
|
||||
e.preventDefault();
|
||||
$.BlobEditor.Placeholder.clearAll();
|
||||
//debug('submitting');
|
||||
$(this).unbind('submit');
|
||||
$(this).submit();
|
||||
});
|
||||
};
|
||||
|
||||
$.BlobEditor.Placeholder = $.GollumPlaceholder;
|
||||
})(jQuery);
|
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;
|
||||
}
|
|
@ -37,7 +37,7 @@ li.commit .message {
|
|||
|
||||
li.commit .trees {
|
||||
padding-left: 5px;
|
||||
width: 180px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
li.commit .message a {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<!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>
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-29164163-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
</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
|