From 520d51a55a6d3994bcd96243299d276c83954b2c Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 28 Feb 2013 23:02:14 +0600 Subject: [PATCH] #953 ssh keys initial --- app/controllers/users/users_controller.rb | 17 ++++++++ app/models/ssh_key.rb | 44 ++++++++++++++++++++ config/locales/models/ssh_key.en.yml | 16 +++++++ config/locales/models/ssh_key.ru.yml | 16 +++++++ config/routes.rb | 4 +- db/migrate/20130227102900_create_ssh_keys.rb | 15 +++++++ db/schema.rb | 14 ++++++- spec/models/ssh_key_spec.rb | 5 +++ 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 app/controllers/users/users_controller.rb create mode 100644 app/models/ssh_key.rb create mode 100644 config/locales/models/ssh_key.en.yml create mode 100644 config/locales/models/ssh_key.ru.yml create mode 100644 db/migrate/20130227102900_create_ssh_keys.rb create mode 100644 spec/models/ssh_key_spec.rb diff --git a/app/controllers/users/users_controller.rb b/app/controllers/users/users_controller.rb new file mode 100644 index 000000000..3f293ed29 --- /dev/null +++ b/app/controllers/users/users_controller.rb @@ -0,0 +1,17 @@ +# -*- encoding : utf-8 -*- +class Users::UsersController < Users::BaseController + skip_before_filter :authenticate_user!, :only => :allowed + + def allowed + key = SSHKey.find(params[:key_id]) + owner_name, project_name = params[:project].split '/' + project = Project.find_by_owner_and_name!(owner_name, project_name ? project_name : '!') + action = case params[:action_type] + when 'git-upload-pack' + then :read + when 'git-receive-pack' + then :write + end + render :inline => Ability.new(key.user).can?(action, project) ? 'true' : 'false' + end +end diff --git a/app/models/ssh_key.rb b/app/models/ssh_key.rb new file mode 100644 index 000000000..fac8bf6f1 --- /dev/null +++ b/app/models/ssh_key.rb @@ -0,0 +1,44 @@ +# This class is based on +# https://github.com/gitlabhq/gitlabhq/blob/15c0e58a49d623a0f8747e1d7e74364324eeb79f/app/models/key.rb + +class SSHKey < ActiveRecord::Base + SHELL_KEY_COMMAND = "sudo ~#{APP_CONFIG['shell_user']}/gitlab-shell/bin/gitlab-keys" + + belongs_to :user + attr_accessible :key, :name + + before_validation lambda { self.key = key.strip if key.present? } + before_validation :set_fingerprint + + validates :name, :presence => true, :length => {:maximum => 255} + validates :key, :presence => true, :length => {:maximum => 5000}, format: { :with => /ssh-.{3} / }, uniqueness: true + + def self.manage_key(action, key_id, key_content) + #system SHELL_KEY_COMMAND, action, key_id, key_content + system "#{SHELL_KEY_COMMAND} #{action} #{key_id} \"#{key_content}\"" + #[SHELL_KEY_COMMAND, action, key_id, key_content].join(' ') + end + + protected + + def set_fingerprint + return false unless key + + file = Tempfile.new('key_file') + begin + file.puts key + file.rewind + fingerprint_output = `ssh-keygen -lf #{file.path} 2>&1` # Catch stderr. + ensure + file.close + file.unlink # deletes the temp file + end + error_message = t('activerecord.errors.ssh_key.wrong_key') + if $?.exitstatus != 0 + errors.add :key, error_message + else + self.fingerprint = fingerprint_output.split.try(:[], 1) + errors.add(:key, error_message) if fingerprint.blank? + end + end +end diff --git a/config/locales/models/ssh_key.en.yml b/config/locales/models/ssh_key.en.yml new file mode 100644 index 000000000..3c6a8638f --- /dev/null +++ b/config/locales/models/ssh_key.en.yml @@ -0,0 +1,16 @@ +en: + activerecord: + errors: + ssh_key: + wrong_key: Wrong public key + models: + ssh_key: SSH Key + attributes: + ssh_key: + id: Id + name: Name + fingerprint: Fingerprint + created_at: Created + updated_at: Updated + user_id: User + key: Key diff --git a/config/locales/models/ssh_key.ru.yml b/config/locales/models/ssh_key.ru.yml new file mode 100644 index 000000000..68340a821 --- /dev/null +++ b/config/locales/models/ssh_key.ru.yml @@ -0,0 +1,16 @@ +ru: + activerecord: + errors: + ssh_key: + wrong_key: Неправильный публичный ключ + models: + ssh_key: SSH ключ + attributes: + ssh_key: + id: Id + name: Имя + fingerprint: Отпечаток + created_at: Создано + updated_at: Обновлено + user_id: Пользователь + key: Ключ diff --git a/config/routes.rb b/config/routes.rb index a48a14a33..56428bcde 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -81,6 +81,7 @@ Rosa::Application.routes.draw do resources :product_build_lists, :only => [:index, :show, :destroy, :create] do put :cancel, :on => :member end + resources :ssh_keys, :only => [:index, :create, :destroy] end end @@ -108,6 +109,7 @@ Rosa::Application.routes.draw do get :system end put :reset_auth_token, :on => :member + resources :ssh_keys, :only => [:index, :create, :destroy] end resources :register_requests, :only => [:index] do put :update, :on => :collection @@ -194,8 +196,8 @@ Rosa::Application.routes.draw do put :notifiers end end - resources :register_requests, :only => [:new, :create], :format => /ru|en/ #view support only two languages + get '/allowed' => 'users#allowed' end scope :module => 'groups' do diff --git a/db/migrate/20130227102900_create_ssh_keys.rb b/db/migrate/20130227102900_create_ssh_keys.rb new file mode 100644 index 000000000..c06929945 --- /dev/null +++ b/db/migrate/20130227102900_create_ssh_keys.rb @@ -0,0 +1,15 @@ +class CreateSshKeys < ActiveRecord::Migration + def change + create_table :ssh_keys do |t| + t.string :name, :null => false + t.text :key, :null => false + t.string :fingerprint, :null => false + t.integer :user_id, :null => false + + t.timestamps + end + + add_index :ssh_keys, :key, :unique => true + add_index :ssh_keys, :user_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 21a31e00f..01b180546 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130222112415) do +ActiveRecord::Schema.define(:version => 20130227102900) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false @@ -453,6 +453,18 @@ ActiveRecord::Schema.define(:version => 20130222112415) do t.boolean "new_associated_build", :default => true end + create_table "ssh_keys", :force => true do |t| + t.string "name", :null => false + t.text "key", :null => false + t.string "fingerprint", :null => false + t.integer "user_id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + add_index "ssh_keys", ["key"], :name => "index_ssh_keys_on_key", :unique => true + add_index "ssh_keys", ["user_id"], :name => "index_ssh_keys_on_user_id" + create_table "subscribes", :force => true do |t| t.string "subscribeable_type" t.integer "user_id" diff --git a/spec/models/ssh_key_spec.rb b/spec/models/ssh_key_spec.rb new file mode 100644 index 000000000..be9956521 --- /dev/null +++ b/spec/models/ssh_key_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe SshKey do + pending "add some examples to (or delete) #{__FILE__}" +end