diff --git a/Gemfile b/Gemfile index ca599a431..1a6337614 100644 --- a/Gemfile +++ b/Gemfile @@ -55,10 +55,10 @@ group :production do end group :development do - gem 'shotgun' - # gem 'letter_opener' + gem 'mailcatcher' # 'letter_opener' gem 'rails3-generators' gem 'hirb' + gem 'shotgun' # deploy gem 'whenever', :require => false gem 'capistrano', :require => false diff --git a/Gemfile.lock b/Gemfile.lock index 871d3cf5b..c66e47c28 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,23 +100,24 @@ GEM delayed_job_active_record (0.3.2) activerecord (> 2.1.0) delayed_job (~> 3.0.0) - devise (2.0.0) + devise (2.0.1) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.0.3) railties (~> 3.1) warden (~> 1.1) diff-lcs (1.1.3) erubis (2.7.0) + eventmachine (0.12.10) execjs (1.3.0) multi_json (~> 1.0) expression_parser (0.9.0) - factory_girl (2.5.1) - activesupport + factory_girl (2.5.2) + activesupport (>= 2.3.9) factory_girl_rails (1.6.0) factory_girl (~> 2.5.0) railties (>= 3.0.0) fssm (0.2.8.1) - 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) @@ -148,6 +149,15 @@ GEM i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) + mailcatcher (0.5.5) + activesupport (~> 3.0) + eventmachine (~> 0.12) + haml (~> 3.1) + mail (~> 2.3) + sinatra (~> 1.2) + skinny (~> 0.2) + sqlite3 (~> 1.3) + thin (~> 1.2) meta-tags (1.2.4) actionpack mime-types (1.17.2) @@ -234,7 +244,7 @@ GEM i18n (>= 0.5.0) sanitize (2.0.3) nokogiri (>= 1.4.4, < 1.6) - sass (3.1.14) + sass (3.1.15) sass-rails (3.2.4) railties (~> 3.2.0) sass (>= 3.1.10) @@ -245,13 +255,21 @@ GEM rack (~> 1.3, >= 1.3.6) rack-protection (~> 1.2) tilt (~> 1.3, >= 1.3.3) + skinny (0.2.0) + eventmachine (~> 0.12) + thin (~> 1.2) sprockets (2.1.2) hike (~> 1.2) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + sqlite3 (1.3.5) state_machine (1.1.2) therubyracer (0.9.9) libv8 (~> 3.3.10) + 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) @@ -302,6 +320,7 @@ DEPENDENCIES highline (~> 1.6.11) hirb jquery-rails (~> 2.0.0) + mailcatcher meta-tags (~> 1.2.4) newrelic_rpm (~> 3.3.1) omniauth (~> 1.0.2) diff --git a/app/assets/javascripts/blob.editor.js b/app/assets/javascripts/blob.editor.js new file mode 100644 index 000000000..edcf8bf1c --- /dev/null +++ b/app/assets/javascripts/blob.editor.js @@ -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); diff --git a/app/controllers/collaborators_controller.rb b/app/controllers/collaborators_controller.rb index c033a75b4..d46c40305 100644 --- a/app/controllers/collaborators_controller.rb +++ b/app/controllers/collaborators_controller.rb @@ -6,9 +6,10 @@ 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 + def index redirect_to edit_project_collaborators_path(@project) end @@ -49,7 +50,7 @@ class CollaboratorsController < ApplicationController groups_for_removing.each do |u| Relation.by_object(u).by_target(@project).each {|r| r.destroy} end - + # Create relations Relation::ROLES.each { |r| #users_for_creating = users_for_creating params[:user].keys.map{|p| p.to_i} - @project.collaborators.map(&:id) @@ -129,4 +130,8 @@ class CollaboratorsController < ApplicationController def find_groups @groups = @project.groups#Group.all end + + def authorize_collaborators + authorize! :update, @project + end end diff --git a/app/controllers/git/blobs_controller.rb b/app/controllers/git/blobs_controller.rb index 0bfe6b4b4..0b93db28f 100644 --- a/app/controllers/git/blobs_controller.rb +++ b/app/controllers/git/blobs_controller.rb @@ -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 diff --git a/app/controllers/git/trees_controller.rb b/app/controllers/git/trees_controller.rb index 081fa7e8b..94b6b91e0 100644 --- a/app/controllers/git/trees_controller.rb +++ b/app/controllers/git/trees_controller.rb @@ -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) diff --git a/app/controllers/register_requests_controller.rb b/app/controllers/register_requests_controller.rb new file mode 100644 index 000000000..74ddd6627 --- /dev/null +++ b/app/controllers/register_requests_controller.rb @@ -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 diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index a79e713b8..b334262e3 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -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 diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index a7f1163cf..0addc764b 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -12,7 +12,7 @@ module DiffHelper res += "" res += "" - res.html_safe.force_encoding(Encoding.default_internal || Encoding::UTF_8) + res.html_safe.encode_to_default end end diff --git a/app/helpers/git_helper.rb b/app/helpers/git_helper.rb index f302b5aed..fef549d7e 100644 --- a/app/helpers/git_helper.rb +++ b/app/helpers/git_helper.rb @@ -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 += "#{i}\n" } diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index 9b406a88b..05ac815ab 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -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 diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 4fcc5488b..6609ac427 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -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 diff --git a/app/models/ability.rb b/app/models/ability.rb index 0ca631e51..113b50dd1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -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 @@ -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 diff --git a/app/models/git/repository.rb b/app/models/git/repository.rb index 4ed82b210..c1d0fec4d 100644 --- a/app/models/git/repository.rb +++ b/app/models/git/repository.rb @@ -2,16 +2,17 @@ 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 commits('master', 1).first end - + def to_s name end @@ -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 ") + # + # 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{#} + 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 + # * 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 diff --git a/app/models/register_request.rb b/app/models/register_request.rb new file mode 100644 index 000000000..a0299556f --- /dev/null +++ b/app/models/register_request.rb @@ -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 diff --git a/app/models/user.rb b/app/models/user.rb index 314816ac0..69dac7a6a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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 diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 12b39d4a3..d83f72b9a 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -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 diff --git a/app/views/devise/shared/_links.haml b/app/views/devise/shared/_links.haml index 958f5ec3c..3ae0900da 100644 --- a/app/views/devise/shared/_links.haml +++ b/app/views/devise/shared/_links.haml @@ -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" diff --git a/app/views/git/blobs/_editor.html.haml b/app/views/git/blobs/_editor.html.haml new file mode 100644 index 000000000..9851626e4 --- /dev/null +++ b/app/views/git/blobs/_editor.html.haml @@ -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' diff --git a/app/views/git/blobs/edit.html.haml b/app/views/git/blobs/edit.html.haml new file mode 100644 index 000000000..0452cc04d --- /dev/null +++ b/app/views/git/blobs/edit.html.haml @@ -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') + diff --git a/app/views/git/blobs/show.html.haml b/app/views/git/blobs/show.html.haml index 43127ac7e..14f6e6164 100644 --- a/app/views/git/blobs/show.html.haml +++ b/app/views/git/blobs/show.html.haml @@ -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 diff --git a/app/views/git/repositories/show.html.haml b/app/views/git/repositories/show.html.haml index 41c205ebd..c3131ed82 100644 --- a/app/views/git/repositories/show.html.haml +++ b/app/views/git/repositories/show.html.haml @@ -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==   diff --git a/app/views/git/shared/_navigation.html.haml b/app/views/git/shared/_navigation.html.haml index e09fcb051..fcd292c06 100644 --- a/app/views/git/shared/_navigation.html.haml +++ b/app/views/git/shared/_navigation.html.haml @@ -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) @@ -25,4 +26,4 @@ %span.current= tag.name - else = link_to tag.name, tree_path(@project, :treeish => tag.name) - .clear \ No newline at end of file + .clear diff --git a/app/views/layouts/_counters.html.erb b/app/views/layouts/_counters.html.erb new file mode 100644 index 000000000..7b5fc6144 --- /dev/null +++ b/app/views/layouts/_counters.html.erb @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index ba51619c2..ed9ebf705 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -47,3 +47,4 @@ .both %footer= render "layouts/menu/bottom" + = render 'layouts/counters' unless current_user.try(:admin?) diff --git a/app/views/layouts/sessions.html.haml b/app/views/layouts/sessions.html.haml index f56fa2d68..4b120a493 100644 --- a/app/views/layouts/sessions.html.haml +++ b/app/views/layouts/sessions.html.haml @@ -11,3 +11,5 @@ #box = render :partial => "layouts/flashes" = yield + + = render 'layouts/counters' unless current_user.try(:admin?) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index cab48a9b3..30af680c4 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -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) diff --git a/app/views/register_requests/index.html.haml b/app/views/register_requests/index.html.haml new file mode 100644 index 000000000..a860887aa --- /dev/null +++ b/app/views/register_requests/index.html.haml @@ -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 + + + =# 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(); + }); + }); diff --git a/app/views/register_requests/new.html.haml b/app/views/register_requests/new.html.haml new file mode 100644 index 000000000..5ff201c35 --- /dev/null +++ b/app/views/register_requests/new.html.haml @@ -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 diff --git a/app/views/user_mailer/invite_approve_notification.html.haml b/app/views/user_mailer/invite_approve_notification.html.haml new file mode 100644 index 000000000..d669eb178 --- /dev/null +++ b/app/views/user_mailer/invite_approve_notification.html.haml @@ -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» diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml index 92ce0aef8..f48d594f0 100644 --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -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") diff --git a/app/views/wiki/_history.html.haml b/app/views/wiki/_history.html.haml index a1f66a2a8..bb14ce8e2 100644 --- a/app/views/wiki/_history.html.haml +++ b/app/views/wiki/_history.html.haml @@ -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 diff --git a/app/views/wiki/_project_short.html.haml b/app/views/wiki/_project_short.html.haml index 4697ab479..258ea3373 100644 --- a/app/views/wiki/_project_short.html.haml +++ b/app/views/wiki/_project_short.html.haml @@ -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) diff --git a/config/environments/development.rb b/config/environments/development.rb index 66526d53c..250ad7fd9 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -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 diff --git a/config/locales/en.yml b/config/locales/en.yml index cbb84b4c2..8806dd1db 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -661,6 +661,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 @@ -915,6 +919,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 diff --git a/config/locales/ru.yml b/config/locales/ru.yml index f7702f2d7..8c8fac327 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -533,6 +533,10 @@ ru: revert_success: Изменения успешно откачены patch_does_not_apply: Не удалось откатить изменения + blob: + successfully_updated: Файл '%{name}' успешно обновлен + updating_error: Ошибка обновления файла '%{name}' + attributes: password: Пароль password_confirmation: Подтверждение @@ -777,3 +781,4 @@ ru: new_user_notification: Регистрация на проекте «%{ project_name }» issue_assign_notification: Вам назначили задачу new_commit_comment_notification: Новый комментарий к коммиту + invite_approve_notification: Приглашение в ABF diff --git a/config/routes.rb b/config/routes.rb index f03dcbf0c..cf410d285 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,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 @@ -180,12 +189,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 diff --git a/db/migrate/20120209135822_create_register_requests.rb b/db/migrate/20120209135822_create_register_requests.rb new file mode 100644 index 000000000..6ae743fa7 --- /dev/null +++ b/db/migrate/20120209135822_create_register_requests.rb @@ -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 diff --git a/db/migrate/20120210141153_add_more_fields_to_register_requests.rb b/db/migrate/20120210141153_add_more_fields_to_register_requests.rb new file mode 100644 index 000000000..cbe0dc71a --- /dev/null +++ b/db/migrate/20120210141153_add_more_fields_to_register_requests.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 77c34afd6..9e4ecacb8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,12 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120206225130) do +ActiveRecord::Schema.define(:version => 20120210141153) do create_table "arches", :force => true do |t| t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "arches", ["name"], :name => "index_arches_on_name", :unique => true @@ -25,8 +25,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "user_id" t.string "provider" t.string "uid" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "authentications", ["provider", "uid"], :name => "index_authentications_on_provider_and_uid", :unique => true @@ -37,8 +37,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "arch_id" t.integer "pl_id" t.integer "bpl_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "build_list_items", :force => true do |t| @@ -46,8 +46,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "level" t.integer "status" t.integer "build_list_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "version" end @@ -61,8 +61,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "project_id" t.integer "arch_id" t.datetime "notified_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "is_circle", :default => false t.text "additional_repos" t.string "name" @@ -85,16 +85,16 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "name" t.string "ancestry" t.integer "projects_count", :default => 0, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "comments", :force => true do |t| t.string "commentable_type" t.integer "user_id" t.text "body" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.decimal "commentable_id", :precision => 50, :scale => 0 end @@ -102,8 +102,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "name", :null => false t.integer "project_id", :null => false t.integer "owner_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "delayed_jobs", :force => true do |t| @@ -115,8 +115,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.datetime "locked_at" t.datetime "failed_at" t.string "locked_by" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "queue" end @@ -128,8 +128,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "distro" t.string "platform" t.integer "counter", :default => 0 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "event_logs", :force => true do |t| @@ -144,15 +144,15 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "controller" t.string "action" t.text "message" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "groups", :force => true do |t| t.string "name" t.integer "owner_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "uname" t.integer "own_projects_count", :default => 0, :null => false end @@ -164,8 +164,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "title" t.text "body" t.string "status", :default => "open" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true @@ -174,8 +174,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "description" t.string "name" t.integer "parent_platform_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "released", :default => false t.integer "owner_id" t.string "owner_type" @@ -188,8 +188,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "platform_id" t.string "login" t.string "password" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "user_id" end @@ -197,8 +197,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "product_id" t.integer "status", :default => 2, :null => false t.datetime "notified_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "product_build_lists", ["product_id"], :name => "index_product_build_lists_on_product_id" @@ -208,8 +208,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.integer "platform_id", :null => false t.integer "build_status", :default => 2, :null => false t.string "build_path" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "build_script" t.text "counter" t.text "ks" @@ -229,8 +229,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "name" t.string "version" t.datetime "file_mtime" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "platform_id" end @@ -239,14 +239,14 @@ ActiveRecord::Schema.define(:version => 20120206225130) do create_table "project_to_repositories", :force => true do |t| t.integer "project_id" t.integer "repository_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "projects", :force => true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "owner_id" t.string "owner_type" t.string "visibility", :default => "open" @@ -264,21 +264,36 @@ ActiveRecord::Schema.define(:version => 20120206225130) 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" t.integer "target_id" t.string "target_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "role" end create_table "repositories", :force => true do |t| t.string "description", :null => false t.integer "platform_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "name", :null => false t.integer "owner_id" t.string "owner_type" @@ -288,8 +303,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "name", :null => false t.integer "arch_id", :null => false t.integer "project_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "rpms", ["project_id", "arch_id"], :name => "index_rpms_on_project_id_and_arch_id" @@ -302,8 +317,8 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.boolean "new_comment_reply", :default => true t.boolean "new_issue", :default => true t.boolean "issue_assign", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "new_comment_commit_owner", :default => true t.boolean "new_comment_commit_repo_owner", :default => true t.boolean "new_comment_commit_commentor", :default => true @@ -313,26 +328,26 @@ ActiveRecord::Schema.define(:version => 20120206225130) do t.string "subscribeable_id" t.string "subscribeable_type" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "status", :default => true t.integer "project_id" end create_table "users", :force => true do |t| t.string "name" - t.string "email", :default => "", :null => false - t.string "encrypted_password", :default => "", :null => false + t.string "email", :default => "", :null => false + t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "reset_password_token" - t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "ssh_key" t.string "uname" t.string "role" - t.string "language", :default => "en" - t.integer "own_projects_count", :default => 0, :null => false + t.string "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 diff --git a/lib/gollum/page.rb b/lib/gollum/page.rb index 5850f0b3b..9fb1a31f9 100644 --- a/lib/gollum/page.rb +++ b/lib/gollum/page.rb @@ -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 diff --git a/lib/gollum/wiki.rb b/lib/gollum/wiki.rb index 9916eea08..14e8ae614 100644 --- a/lib/gollum/wiki.rb +++ b/lib/gollum/wiki.rb @@ -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 diff --git a/lib/grit/repo.rb b/lib/grit/repo.rb index d24bb6ff3..998ff7b30 100644 --- a/lib/grit/repo.rb +++ b/lib/grit/repo.rb @@ -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 diff --git a/lib/preregistration/devise/preregistration.rb b/lib/preregistration/devise/preregistration.rb new file mode 100644 index 000000000..da2635184 --- /dev/null +++ b/lib/preregistration/devise/preregistration.rb @@ -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 diff --git a/public/invite.html b/public/invite.html new file mode 100644 index 000000000..4feb0c004 --- /dev/null +++ b/public/invite.html @@ -0,0 +1,126 @@ + + + + + Сборочная среда + + + + +
+ +
+ + +
+ Платформа разработки и управления жизненным циклом дистрибутивов: от исходного кода до ISO-образов +
+ +
+
+
+ + +
+
+

+ Приветствуем Вас!

+ Вы находитесь на странице размещения заявок на участие в бета-тестировании сборочного сервиса ABF компании РОСА.

+ В первую очередь одобряются заявки от потенциальных майнтейнеров и представителей дистрибутивных команд.

+ Ознакомиться с документацией можно здесь.

+ Мы будем рады ответить на Ваши вопросы на форуме проекта. +

+ +
+
+ + +
+
+

Хочу стать бета-тестером ABF!

+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ +
+
+
+ +
+
+ +
+
+
+ +
+ + + + + diff --git a/public/pics/bg-signup.png b/public/pics/bg-signup.png new file mode 100644 index 000000000..79676f161 Binary files /dev/null and b/public/pics/bg-signup.png differ diff --git a/public/pics/bg.png b/public/pics/bg.png new file mode 100644 index 000000000..62e74e049 Binary files /dev/null and b/public/pics/bg.png differ diff --git a/public/pics/button-green-disabled.png b/public/pics/button-green-disabled.png new file mode 100644 index 000000000..21159cb78 Binary files /dev/null and b/public/pics/button-green-disabled.png differ diff --git a/public/pics/button-green-hover.png b/public/pics/button-green-hover.png new file mode 100644 index 000000000..b639aa0ab Binary files /dev/null and b/public/pics/button-green-hover.png differ diff --git a/public/pics/button-green-normal.png b/public/pics/button-green-normal.png new file mode 100644 index 000000000..5fb90051c Binary files /dev/null and b/public/pics/button-green-normal.png differ diff --git a/public/pics/button-green-press.png b/public/pics/button-green-press.png new file mode 100644 index 000000000..66ce78c4a Binary files /dev/null and b/public/pics/button-green-press.png differ diff --git a/public/pics/flag.png b/public/pics/flag.png new file mode 100644 index 000000000..85b84ce4f Binary files /dev/null and b/public/pics/flag.png differ diff --git a/public/pics/logo.png b/public/pics/logo.png new file mode 100644 index 000000000..0fbda66db Binary files /dev/null and b/public/pics/logo.png differ diff --git a/public/pics/square.png b/public/pics/square.png new file mode 100644 index 000000000..a6f4b5f9b Binary files /dev/null and b/public/pics/square.png differ diff --git a/public/styles/prereg.css b/public/styles/prereg.css new file mode 100644 index 000000000..b958cc409 --- /dev/null +++ b/public/styles/prereg.css @@ -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; +} \ No newline at end of file diff --git a/public/thanks.html b/public/thanks.html new file mode 100644 index 000000000..0e9f8ae7e --- /dev/null +++ b/public/thanks.html @@ -0,0 +1,72 @@ + + + + + Сборочная среда + + + + +
+ +
+ + +
+ Платформа разработки и управления жизненным циклом дистрибутивов: от исходного кода до ISO-образов +
+ +
+
+
+ + +
+
+

+ Спасибо!

+ Благодарим за интерес к нашему сервису ABF!

+ Приглашение будет выслано вам по указанной электронной почте.

+ Приглашаем Вас на форум проекта, где мы будем рады ответить на Ваши вопросы и получить Ваши пожелания.

+ Ознакомиться с документацией можно здесь. +

+
+ +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/spec/factories/register_requests.rb b/spec/factories/register_requests.rb new file mode 100644 index 000000000..7fd9c1446 --- /dev/null +++ b/spec/factories/register_requests.rb @@ -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 diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb index 8b48e44f6..597d5dd38 100644 --- a/spec/models/cancan_spec.rb +++ b/spec/models/cancan_spec.rb @@ -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) diff --git a/spec/models/register_request_spec.rb b/spec/models/register_request_spec.rb new file mode 100644 index 000000000..eea8bb192 --- /dev/null +++ b/spec/models/register_request_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe RegisterRequest do + pending "add some examples to (or delete) #{__FILE__}" +end