Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ db/development.sqlite3.save
db/development_structure.sql
db/schema.rb
config/initializers/google_parameters.rb
config/*.pem
cache
test/tmp
nbproject
48 changes: 48 additions & 0 deletions app/controllers/admin/friends_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Admin
class FriendsController < ApplicationController
layout 'admin'
before_filter :admin_required
before_filter :load_public_key, :only => [:index]
before_filter :find_friend, :only => [:edit, :update, :destroy]

def index
@friends = Friend.for_list
end

def new
@friend = Friend.new
end

def create
@friend = Friend.new(params[:friend])

redirect_to admin_friends_path if @friend.save
end

def edit
end

def update
redirect_to admin_friends_path if @friend.update_attributes(params[:friend])
end

def destroy
@friend.destroy

redirect_to admin_friends_path
end

private

def load_public_key
public_key_file = File.join(Rails.root, "config/friendlist_public.pem")

@public_key = OpenSSL::PKey::RSA.new(File.read(public_key_file)) if FileTest.exists? public_key_file
end

def find_friend
@friend = Friend.find(params[:id])
end

end
end
41 changes: 41 additions & 0 deletions app/controllers/friends_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class FriendsController < ApplicationController
before_filter :load_private_key
protect_from_forgery :except => [:status, :user_data]

def status
unless @private_key
head :precondition_failed
else
hostname = @private_key.private_decrypt([params[:message]].pack("H*"))
@friend = Friend.first(:conditions => {:hostname => hostname}, :select => 'id, hostname, public_key')
puts @friend.inspect

respond_to do |format|
format.json { render :json => @friend }
end
end
end

def user_data
public_key = OpenSSL::PKey::RSA.new(Friend.find_by_hostname(params[:hostname]).public_key)
login = @private_key.private_decrypt([params[:message]].pack("H*"))

if @private_key && public_key && public_key.verify(OpenSSL::Digest::SHA1.new, [params[:sign]].pack("H*"), login)
@user = User.first(:conditions => {:login => login},
:select => ('id, login, email, first_name, last_name, country, city, occupation'))

respond_to do |format|
format.json { render :json => @user }
end
else
head :precondition_failed
end
end

private

def load_private_key
private_key_file = File.join(Rails.root, "config/friendlist_private.pem")
@private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file)) if FileTest.exists? private_key_file
end
end
2 changes: 1 addition & 1 deletion app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def create
current_user.remember_me unless current_user.remember_token?
cookies[:auth_token] = { :value => self.current_user.remember_token, :expires => self.current_user.remember_token_expires_at }
end
redirect_back_or_default(user_path(:id => current_user.id))
redirect_back_or_default('/')
flash[:notice] = t('message.session.logged', :user_name => h(params[:login]))
else
flash[:error] = t('message.session.failed')
Expand Down
75 changes: 40 additions & 35 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,45 +1,28 @@
# Controller for work with users: create(signup), update, delete, activate

class UsersController < ApplicationController
include ActiveScaffold

before_filter :login_required, :only => [:current]
before_filter :scaffold_action, :set_common_columns_info, :only => [:edit, :update, :new, :create]
before_filter(:current_user_only, :unless => :admin?,
:except => [:restore, :activate, :current,:new, :create])


USER_EDITABLE_COLUMNS = [:password, :password_confirmation, :email, :first_name, :last_name, :country, :city,
:occupation, :projects, :subscribed, :subscribed_talks]
ONLY_CREATE_COLUMNS = [:login]
COLUMNS = ONLY_CREATE_COLUMNS + USER_EDITABLE_COLUMNS
PRIORITY_COUNTRIES = ['Belarus', 'Ukraine', 'Russia']

LOCALIZATION_LABEL_PREFIX = "label.user."
LOCALIZATION_DESCRIPTION_PREFIX = "description.user."

active_scaffold :users do
cls = UsersController
self.actions = [:create, :update]
self.columns = cls::COLUMNS
self.create.columns = cls::COLUMNS
self.update.columns = cls::USER_EDITABLE_COLUMNS

self.columns[:subscribed].form_ui = :checkbox
self.columns[:subscribed_talks].form_ui = :checkbox
self.columns[:password].form_ui = :password
self.columns[:password_confirmation].form_ui = :password
self.columns[:country].form_ui = :country
self.columns[:country].options[:priority] = cls::PRIORITY_COUNTRIES
User::REQUIRED_FIELDS.each{|i| self.columns[i].required = true }
before_filter :login_required, :only => [:show, :index, :edit, :update, :current]

def signup
end

def list
redirect_to user_path(:id => current_user.id)
# render new.rhtml
def new
@user_friends = Friend.check_by_login params[:login] if params[:login]
@user = User.new @user_friends.values.first if @user_friends.values.length > 0
end

def index
redirect_to user_path(:id => current_user.id)
def create
cookies.delete :auth_token
@user = User.new(params[:user])
if @user.save
UserMailer.deliver_signup_notification(@user)
self.current_user = @user
flash[:notice] = t('message.user.registred')
redirect_to user_path(:id => current_user.id, :lang => params[:lang])
else
render :action => 'new'
end
end

def current
Expand Down Expand Up @@ -140,4 +123,26 @@ def random_pronouncable_password(size = 4)
end
r
end

def edit
@user = User.find params[:id]
unless @user.editable_by? current_user
return render(:text =>t('message.common.access_denied'), :status=> 403)
end
end

def update
@user = User.find params[:id]

unless @user.editable_by?(current_user)
return render(:text =>t('message.common.access_denied'), :status=> 403)
end

flash[:notice] = t('message.user.login_change') if params[:user].delete(:login)
if(@user.update_attributes(params[:user]))
redirect_to user_path(:id=>@user)
else
render :action => "users/edit"
end
end
end
23 changes: 23 additions & 0 deletions app/helpers/admin/friends_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Admin
module FriendsHelper

def status code
case code
when :bad_public_key
t ".status.bad_public_key"
when 201
t ".status.ok"
when 412
t ".status.precondition_failed"
when 404
when 0
when nil
t ".status.not_responding"
else
code
end
end

end
end

15 changes: 1 addition & 14 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
module UsersHelper
PRIORITY_COUNTRIES = ['Belarus', 'Ukraine', 'Russia']

def describe_user(user)
translate('message.user.describe', :full_name => user.full_name,
translate('message.user.describe', :full_name => user.full_name,
:country => user.country,
:city => user.city)
end

def active_scaffold_input_country(column, options)
priority = PRIORITY_COUNTRIES
select_options = {:prompt => as_(:_select_)}
select_options.merge!(options)
country_select(:record, column.name, column.options[:priority] || priority, select_options, column.options)
end

def as_(param, opts={})
t("label.user.#{param}", :default => t("label.common.#{param}"))
end
end
90 changes: 90 additions & 0 deletions app/models/friend.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
class Friend < ActiveRecord::Base

def self.check_by_login login
friends = Friend.all
friend_hostnames = friends.inject({}) do |res, friend|
res[friend.hostname] = friend.id

res
end

private_key_file = File.join(Rails.root, "config/friendlist_private.pem")
private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file)) rescue nil

if private_key
checks = friends.inject([]) do |res, friend|
public_key = OpenSSL::PKey::RSA.new(friend.public_key) rescue nil

if public_key
message = public_key.public_encrypt(login).unpack("H*")[0]
sign = private_key.sign(OpenSSL::Digest::SHA1.new, login).unpack("H*")[0]

res.push({ :url => friend.hostname + 'friends/user_data.json',
:post_fields => { 'hostname' => friend.hostname,
'message' => message,
'sign' => sign } })
end

res
end

friend_statuses = {}
require 'curb'
#Curl::Multi.post(checks, {:follow_location => true}, {:pipeline => true}) do |easy|
# friend_statuses[friend_hostnames[easy.url.chomp "friends/user_data.json"]] = easy.response_code
#end
checks.each do |check|
c = Curl::Easy.http_post(check[:url],
Curl::PostField.content('message', check[:post_fields]['message']),
Curl::PostField.content('sign', check[:post_fields]['sign']),
Curl::PostField.content('hostname', check[:post_fields]['hostname']))

friend_statuses[friend_hostnames[check[:url].chomp "friends/user_data.json"]] = JSON.parse c.body_str rescue nil
end

friend_statuses
end
end

def self.for_list
friends = Friend.all

friend_hostnames = friends.inject({}) do |res, friend|
res[friend.hostname] = friend.id

res
end

friend_statuses = {}
checks = friends.inject([]) do |res, friend|
public_key = OpenSSL::PKey::RSA.new(friend.public_key) rescue nil

unless public_key
friend_statuses[friend.id] = :bad_public_key
else
message = public_key.public_encrypt('http://localhost:3030/').unpack("H*")[0]
res.push({ :url => friend.hostname + 'friends/status.json', :post_fields => { 'message' => message, 'id' => friend.id } })
end

res
end

require 'curb'
#Curl::Multi.post(checks, {:follow_location => true}, {:pipeline => true}) do |easy|
# friend_statuses[friend_hostnames[easy.url.chomp "friends/status.json"]] = easy.response_code
#end
checks.each do |check|
c = Curl::Easy.http_post(check[:url],
Curl::PostField.content('message', check[:post_fields]['message']),
Curl::PostField.content('id', check[:post_fields]['id']))


friend_statuses[friend_hostnames[check[:url].chomp "friends/status.json"]] = c.response_code
end

friends.collect do |friend|
{ :id => friend.id, :hostname => friend.hostname, :status => friend_statuses[friend.id] }
end
end

end
11 changes: 11 additions & 0 deletions app/views/admin/friends/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<%= f.error_messages %>

<div>
<%= f.label :hostname, t('.hostname') %>
<%= f.text_field :hostname %>
</div>

<div>
<%= f.label :public_key, t('.public_key') %><br />
<%= f.text_area :public_key, :cols => 80 %>
</div>
8 changes: 8 additions & 0 deletions app/views/admin/friends/_friend.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<tr>
<td><%= friend[:hostname] %></td>
<td><%= status friend[:status] %></td>
<td>
<%= link_to t('.edit'), edit_admin_friend_path(:id => friend[:id], :lang => params[:lang]) %>
<%= link_to t('.delete'), admin_friend_path(:id => friend[:id], :lang => params[:lang]), :method => :delete %>
</td>
</tr>
5 changes: 5 additions & 0 deletions app/views/admin/friends/_public_key.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<% if key %>
<pre><%= key %></pre>
<% else %>
<%= t('.generate_key_pair') %>
<% end %>
5 changes: 5 additions & 0 deletions app/views/admin/friends/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= form_for(@friend, :url => admin_friend_path(:id => @friend.id, :lang => params[:lang]), :method => :put) do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>

<%= f.submit t('label.common.update') %>
<% end %>
20 changes: 20 additions & 0 deletions app/views/admin/friends/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<h2><%= t('.friendlist') %></h2>

<%= link_to t('.create'), new_admin_friend_path %>

<table>
<thead>
<tr>
<th><%= t('.hostname') %></th>
<th><%= t('.status') %></th>
<th>&nbsp;</th>
</tr>
</thead>

<tbody>
<%= render :partial => 'friend', :collection => @friends %>
</tbody>
</table>

<%= render :partial => 'public_key', :locals => { :key => @public_key } %>

5 changes: 5 additions & 0 deletions app/views/admin/friends/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<%= form_for(@friend, :url => admin_friends_path(:lang => params[:lang])) do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>

<%= f.submit t('label.common.create') %>
<% end %>
Loading