lam_auth 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,143 @@
1
+ Аутентификация для спецпроектов [Lookatme](http://www.lookatme.ru) и [The Village](http://www.the-village.ru)
2
+
3
+ ## Установка
4
+
5
+ gem install lam_auth
6
+
7
+ После установки/добавления в Gemfile:
8
+
9
+ rails generate lam_auth
10
+
11
+ после этого нужно добавить настройки приложения в `config/lam_auth.yml`.
12
+
13
+ Для спецпроектов The Village необходимо в `config/lam_auth.yml` добавить:
14
+
15
+ site: village
16
+
17
+ ## Подключение панели
18
+
19
+ Подключить js-код в head:
20
+
21
+ <%= lam_auth_include_tag %>
22
+
23
+ Затем:
24
+
25
+ <div id="lam-root"></div>
26
+ <%= lam_auth_init_tag %>
27
+
28
+ В случае с The Village дефолтный `id` панели `village-root`.
29
+
30
+ ## Модель
31
+
32
+ При аутентификации Lookatme/The Village возвращают данные пользователя в следующем виде:
33
+
34
+ ```ruby
35
+ {
36
+ "gender" => "male",
37
+ "last_name" => "Маковский",
38
+ "city" => "Москва",
39
+ "email" => "robotector@gmail.com",
40
+ "userpic" => {
41
+ "medium" => "http://assets3.lookatme.ru/assets/user-userpic/20/38/3/user-userpic-medium.jpg",
42
+ "big" => "http://assets0.lookatme.ru/assets/user-userpic/20/38/3/user-userpic-big.jpg",
43
+ "icon" => "http://assets3.lookatme.ru/assets/user-userpic/20/38/3/user-userpic-icon.jpg",
44
+ "thumb" => "http://assets0.lookatme.ru/assets/user-userpic/20/38/3/user-userpic-thumb.jpg"
45
+ },
46
+ "first_name" => "Шляпа",
47
+ "birthday" => "13-12-1979",
48
+ "login" => "macovsky"}
49
+ ```
50
+
51
+ В модели пользователя нужно подключить `LamAuth`:
52
+
53
+ ```ruby
54
+ class User < ActiveRecord::Base
55
+ include LamAuth::Model
56
+ end
57
+ ```
58
+
59
+ Теперь класс `User` имеет метод `create_or_update_by_auth_data`, принимающий данные пользователя:
60
+
61
+ ```ruby
62
+ def self.create_or_update_by_auth_data(data)
63
+ user = find_or_initialize_by_login(data['login'])
64
+ user.update_attributes! data.slice(*%w{email first_name last_name}).merge(
65
+ 'userpic' => data['userpic']['icon'],
66
+ 'profile' => data.except(*%w{login email first_name last_name userpic})
67
+ )
68
+ user
69
+ end
70
+ ```
71
+
72
+ Предполагает наличие соответствующих атрибутов и сериализацию атрибута `profile`:
73
+
74
+ ```ruby
75
+ class CreateUsers < ActiveRecord::Migration
76
+ def self.up
77
+ create_table(:users) do |t|
78
+ t.string :login, :null => false
79
+ t.string :email, :null => false
80
+ t.string :first_name
81
+ t.string :last_name
82
+ t.string :userpic
83
+ t.text :profile
84
+ t.timestamps
85
+ end
86
+
87
+ add_index :users, :login
88
+ add_index :users, :email
89
+ end
90
+
91
+ def self.down
92
+ drop_table :users
93
+ end
94
+ end
95
+ ```
96
+
97
+ Метод переопределяется для конкретных случаев.
98
+
99
+ ## Контроллер
100
+
101
+ Для подключения самого механизма аутентификации можно, например, использовать [RailsWarden](http://github.com/hassox/rails_warden):
102
+
103
+ ```ruby
104
+ # config/initializers/warden.rb
105
+ Rails.configuration.middleware.use RailsWarden::Manager do |manager|
106
+ manager.default_strategies :cookie_with_access_token
107
+ manager.failure_app = SessionsController
108
+ end
109
+
110
+ Warden::Strategies.add(:cookie_with_access_token) do
111
+ def authenticate!
112
+ access_token = LamAuth.access_token_from_cookie(request.cookies[LamAuth.cookie_id])
113
+ access_token ? success!(User.find_by_access_token(access_token)) : fail
114
+ end
115
+ end
116
+
117
+ # app/controllers/application_controller.rb
118
+ class ApplicationController < ActionController::Base
119
+ protect_from_forgery
120
+
121
+ before_filter :authenticate
122
+ before_filter :logout_if_no_cookie_available, :if => :logged_in?
123
+
124
+ private
125
+
126
+ def logout_if_no_cookie_available
127
+ logout if !LamAuth.access_token_from_cookie(cookies[LamAuth.cookie_id])
128
+ end
129
+ end
130
+
131
+ # app/controllers/sessions_controller.rb
132
+ # Контроллер, который в #unauthenticated рендерит сообщение о необходимости авторизоваться/зарегистрироваться.
133
+ class SessionsController < ApplicationController
134
+ def unauthenticated
135
+ end
136
+ end
137
+ ```
138
+
139
+ На страницах, где аутентификация обязательна, можно использовать соответствующий хелпер `RailsWarden`:
140
+
141
+ ```ruby
142
+ before_filter :authenticate!
143
+ ```
@@ -1,16 +1,10 @@
1
1
  module LamAuth
2
2
  module Generators
3
- class LamAuthGenerator < Rails::Generators::NamedBase
3
+ class LamAuthGenerator < Rails::Generators::Base
4
4
  namespace "lam_auth"
5
5
  source_root File.expand_path("../../templates", __FILE__)
6
6
 
7
- desc "Installs lam_auth: generates a model plus includes required extensions."
8
-
9
- hook_for :orm
10
-
11
- def inject_controller_content
12
- inject_into_class(File.join("app", "controllers", "application_controller.rb"), 'ApplicationController', " lam_auth_for :#{file_path}\n")
13
- end
7
+ desc "Installs lam_auth"
14
8
 
15
9
  def copy_xd_receiver
16
10
  copy_file 'xd_receiver.html', 'public/xd_receiver.html'
@@ -4,12 +4,10 @@
4
4
  <meta charset="UTF-8">
5
5
  <title></title>
6
6
  <script type="text/javascript">
7
- window.opener.LAM.successLogin(window.location.hash.substring(1));
7
+ (window.opener.LAM || window.opener.VLG).successLogin(window.location.hash.substring(1));
8
8
  </script>
9
9
  </head>
10
10
  <body><p>Loading...</p>
11
11
  </body>
12
12
  </html>
13
13
 
14
-
15
-
@@ -1,18 +1,18 @@
1
1
  module LamAuth
2
2
  module Helpers
3
3
  def lam_auth_include_tag
4
- javascript_include_tag(LamAuth.url + "/api/js/LAM.Login.js")
4
+ javascript_include_tag(LamAuth.config['api_url'])
5
5
  end
6
6
 
7
7
  def lam_auth_init_tag(options = {})
8
8
  options.reverse_merge!(
9
- :app_id => LamAuth.config['app_id'],
10
- :panel_node_id => 'lam-root',
9
+ :app_id => LamAuth.app['app_id'],
10
+ :panel_node_id => "#{LamAuth.config['prefix']}-root",
11
11
  :fixed => false
12
12
  )
13
- options.reverse_merge!(:xd_receiver_url => LamAuth.config['return_url']) if LamAuth.config['return_url']
13
+ options.reverse_merge!(:xd_receiver_url => LamAuth.app['return_url']) if LamAuth.app['return_url']
14
14
 
15
- javascript_tag("LAM.init({#{options.map{|k, v| "#{k.to_s.camelize(:lower)}: #{v.inspect}"}.join(",\n")}});")
15
+ javascript_tag("#{LamAuth.config['api']}.init({#{options.map{|k, v| "#{k.to_s.camelize(:lower)}: #{v.inspect}"}.join(",\n")}});")
16
16
  end
17
17
  end
18
18
  end
@@ -3,19 +3,16 @@ require 'net/https'
3
3
  module LamAuth
4
4
  module Model
5
5
  def self.included(base)
6
- base.validates_presence_of :login, :email
7
- base.validates_uniqueness_of :login, :email
8
- base.serialize :profile
9
- base.send(:extend, ClassMethods)
6
+ base.extend ClassMethods
10
7
  end
11
-
8
+
12
9
  module ClassMethods
13
10
  def find_by_access_token(access_token)
14
11
  Rails.logger.info("Trying to authorize a token #{access_token.inspect} ")
15
12
 
16
- lam_uri = LamAuth.uri
17
- http = Net::HTTP.new(lam_uri.host, lam_uri.port)
18
- response = http.get("#{lam_uri.path}/users/me", {'Authorization' => "Token token=\"#{access_token}\""})
13
+ uri = URI.parse(LamAuth.url)
14
+ http = Net::HTTP.new(uri.host, uri.port)
15
+ response = http.get("#{uri.path}/users/me", {'Authorization' => "Token token=\"#{access_token}\""})
19
16
  if response.code == "200"
20
17
  data = ActiveSupport::JSON.decode(response.body)
21
18
  Rails.logger.info("...success: #{data.inspect}")
@@ -24,31 +21,16 @@ module LamAuth
24
21
  Rails.logger.info("...failed with #{response.code}!")
25
22
  nil
26
23
  end
27
- rescue Net::ProtoRetriableError => detail
28
- Rails.logger.info("...failed!")
29
- Rails.logger.info(detail)
30
- nil
31
24
  end
32
25
 
33
26
  def create_or_update_by_auth_data(data)
34
27
  user = find_or_initialize_by_login(data['login'])
35
- user.update_attributes data.slice(*%w{email first_name last_name}).merge(
28
+ user.update_attributes! data.slice(*%w{email first_name last_name}).merge(
36
29
  'userpic' => data['userpic']['icon'],
37
30
  'profile' => data.except(*%w{login email first_name last_name userpic})
38
31
  )
39
32
  user
40
33
  end
41
34
  end
42
-
43
- def name
44
- [first_name, last_name].select(&:present?).join(" ")
45
- end
46
-
47
- def userpic(version = :icon)
48
- pic = read_attribute(:userpic)
49
- return nil if pic.blank?
50
- pic.sub(/user-userpic-\w+/, "user-userpic-#{version}")
51
- end
52
-
53
35
  end
54
36
  end
@@ -1,3 +1,3 @@
1
1
  module LamAuth
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/lam_auth.rb CHANGED
@@ -1,39 +1,48 @@
1
1
  require 'rack/utils'
2
2
  require 'digest/md5'
3
3
 
4
- require 'lam_auth/controller_extensions'
5
4
  require 'lam_auth/helpers'
6
5
  require 'lam_auth/model'
7
- ActionController::Base.extend(LamAuth::ControllerExtensions)
8
6
  ActionController::Base.helper(LamAuth::Helpers)
9
7
 
10
8
  module LamAuth
11
- class LoginRequiredException < Exception
12
- end
13
-
14
9
  class << self
15
- def config
16
- @config ||= YAML.load_file(Rails.root.join("config/lam_auth.yml"))
10
+ def app
11
+ @app ||= YAML.load_file(Rails.root.join("config/lam_auth.yml"))
17
12
  end
18
-
19
- def url
20
- "http://www.lookatme.ru"
13
+
14
+ def config
15
+ {
16
+ 'lookatme' => {
17
+ 'prefix' => 'lam',
18
+ 'url' => 'http://www.lookatme.ru',
19
+ 'api' => 'LAM',
20
+ 'api_url' => 'http://www.lookatme.ru/api/js/LAM.Login.js',
21
+ },
22
+ 'village' => {
23
+ 'prefix' => 'village',
24
+ 'url' => 'http://www.the-village.ru',
25
+ 'api' => 'VLG',
26
+ 'api_url' => 'http://assets0.the-village.ru/api/js/VLG.Login.js',
27
+ }
28
+ }[site]
21
29
  end
22
-
23
- def signup_url
24
- "#{url}/signup"
30
+
31
+ def site
32
+ %w{lookatme village}.include?(app['site']) ? app['site'] : 'lookatme'
25
33
  end
26
34
 
27
- def uri
28
- URI.parse(url)
35
+ def url
36
+ config['url']
29
37
  end
30
38
 
31
39
  def cookie_id
32
- "lam_#{config['app_id']}"
40
+ "#{config['prefix']}_#{app['app_id']}"
33
41
  end
34
-
35
- def valid_cookie?(data)
36
- valid_hash?(parse_cookie_to_hash(data))
42
+
43
+ def access_token_from_cookie(cookie)
44
+ hash = parse_cookie_to_hash(cookie)
45
+ valid_hash?(hash) && hash['access_token']
37
46
  end
38
47
 
39
48
  def parse_cookie_to_hash(data)
@@ -41,7 +50,7 @@ module LamAuth
41
50
  end
42
51
 
43
52
  def valid_hash?(hash)
44
- Digest::MD5.hexdigest(hash.except('sig').sort.map{|v| v.join('=')}.join + LamAuth.config['secret']) == hash['sig']
53
+ Digest::MD5.hexdigest(hash.except('sig').sort.map{|v| v.join('=')}.join + app['secret']) == hash['sig']
45
54
  end
46
55
  end
47
56
  end
metadata CHANGED
@@ -1,63 +1,84 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: lam_auth
3
- version: !ruby/object:Gem::Version
4
- version: 1.1.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
5
  prerelease:
6
+ segments:
7
+ - 2
8
+ - 0
9
+ - 0
10
+ version: 2.0.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Max Macovsky
9
14
  - Anton Platonov
10
15
  autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
- date: 2012-06-27 00:00:00.000000000 Z
18
+
19
+ date: 2012-08-21 00:00:00 -07:00
20
+ default_executable:
14
21
  dependencies: []
15
- description: ''
16
- email:
22
+
23
+ description: ""
24
+ email:
17
25
  - robotector@gmail.com
18
26
  - platosha@lookatme.ru
19
27
  executables: []
28
+
20
29
  extensions: []
30
+
21
31
  extra_rdoc_files: []
22
- files:
32
+
33
+ files:
23
34
  - .gitignore
24
35
  - Gemfile
25
- - README.rdoc
36
+ - README.md
26
37
  - Rakefile
27
38
  - lam_auth.gemspec
28
- - lib/generators/active_record/lam_auth_generator.rb
29
- - lib/generators/active_record/templates/migration.rb
30
- - lib/generators/lam_auth/helpers.rb
31
39
  - lib/generators/lam_auth/lam_auth_generator.rb
32
40
  - lib/generators/templates/lam_auth.yml
33
41
  - lib/generators/templates/xd_receiver.html
34
42
  - lib/lam_auth.rb
35
- - lib/lam_auth/controller_extensions.rb
36
43
  - lib/lam_auth/helpers.rb
37
44
  - lib/lam_auth/model.rb
38
45
  - lib/lam_auth/version.rb
46
+ has_rdoc: true
39
47
  homepage: http://github.com/macovsky/lam_auth
40
48
  licenses: []
49
+
41
50
  post_install_message:
42
51
  rdoc_options: []
43
- require_paths:
52
+
53
+ require_paths:
44
54
  - lib
45
- required_ruby_version: !ruby/object:Gem::Requirement
55
+ required_ruby_version: !ruby/object:Gem::Requirement
46
56
  none: false
47
- requirements:
48
- - - ! '>='
49
- - !ruby/object:Gem::Version
50
- version: '0'
51
- required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
65
  none: false
53
- requirements:
54
- - - ! '>='
55
- - !ruby/object:Gem::Version
56
- version: '0'
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
57
73
  requirements: []
74
+
58
75
  rubyforge_project:
59
- rubygems_version: 1.8.23
76
+ rubygems_version: 1.6.2
60
77
  signing_key:
61
78
  specification_version: 3
62
- summary: Аутентификация для спецпроектов Lookatme
79
+ summary: !binary |
80
+ 0JDRg9GC0LXQvdGC0LjRhNC40LrQsNGG0LjRjyDQtNC70Y8g0YHQv9C10YbQ
81
+ v9GA0L7QtdC60YLQvtCyIExvb2thdG1l
82
+
63
83
  test_files: []
84
+
data/README.rdoc DELETED
@@ -1,42 +0,0 @@
1
- Аутентификация для спецпроектов Lookatme
2
-
3
- == Установка
4
-
5
- gem install lam_auth
6
-
7
- После установки/добавления в Gemfile:
8
-
9
- rails generate lam_auth User
10
-
11
- после этого нужно добавить настройки приложения для соответствующих environment в config/lam_auth.yml.
12
-
13
- == Обработчик LoginRequiredException
14
-
15
- Для actions, где требуется залогиненный пользователь:
16
-
17
- before_filter :login_required
18
-
19
- можно сделать обработчик для LoginRequiredException:
20
-
21
- rescue_from LamAuth::LoginRequiredException, :with => :render_login_required
22
-
23
- private
24
-
25
- def render_login_required
26
- render :file => 'shared/login_required', :layout => 'application', :status => 401
27
- end
28
-
29
- == Подключение панели
30
-
31
- Подключить js-код в head:
32
-
33
- <%= lam_auth_include_tag %>
34
-
35
- Затем:
36
-
37
- <div id="lam-root"></div>
38
- <%= lam_auth_init_tag %>
39
-
40
- == Подробно о механизме аутентификации
41
-
42
- http://mindscan.msk.ru/downloads/lam_auth.pdf
@@ -1,23 +0,0 @@
1
- require 'rails/generators/active_record'
2
- require 'generators/lam_auth/helpers'
3
-
4
- module ActiveRecord
5
- module Generators
6
- class LamAuthGenerator < ActiveRecord::Generators::Base
7
- include LamAuth::Generators::Helpers
8
- source_root File.expand_path("../templates", __FILE__)
9
-
10
- def generate_model
11
- invoke "active_record:model", [name], :migration => false unless model_exists? && behavior == :invoke
12
- end
13
-
14
- def copy_lam_auth_migration
15
- migration_template "migration.rb", "db/migrate/create_#{table_name}"
16
- end
17
-
18
- def inject_lam_auth_content
19
- inject_into_class(model_path, class_name, model_contents) if model_exists?
20
- end
21
- end
22
- end
23
- end
@@ -1,20 +0,0 @@
1
- class Create<%= table_name.camelize %> < ActiveRecord::Migration
2
- def self.up
3
- create_table(:<%= table_name %>) do |t|
4
- t.string :login, :null => false
5
- t.string :email, :null => false
6
- t.string :first_name
7
- t.string :last_name
8
- t.string :userpic
9
- t.text :profile
10
- t.timestamps
11
- end
12
-
13
- add_index :<%= table_name %>, :login
14
- add_index :<%= table_name %>, :email
15
- end
16
-
17
- def self.down
18
- drop_table :<%= table_name %>
19
- end
20
- end
@@ -1,19 +0,0 @@
1
- module LamAuth
2
- module Generators
3
- module Helpers
4
- def model_exists?
5
- File.exists?(File.join(destination_root, model_path))
6
- end
7
-
8
- def model_path
9
- @model_path ||= File.join("app", "models", "#{file_path}.rb")
10
- end
11
-
12
- def model_contents
13
- <<-CONTENT
14
- include LamAuth::Model
15
- CONTENT
16
- end
17
- end
18
- end
19
- end
@@ -1,53 +0,0 @@
1
- module LamAuth
2
- module ControllerExtensions
3
- def lam_auth_for(klass)
4
- class_attribute :user_model_class_name
5
- self.user_model_class_name = klass
6
-
7
- helper_method(:current_user, :logged_in?)
8
- before_filter :login_from_cookie
9
-
10
- extend ClassMethods
11
- include InstanceMethods
12
- protected :logged_in?, :current_user, :current_user=, :access_token, :login_from_cookie, :login_required
13
- end
14
-
15
- module ClassMethods
16
- def user_model_class
17
- user_model_class_name.to_s.classify.constantize
18
- end
19
- end
20
-
21
- module InstanceMethods
22
- def logged_in?
23
- !!current_user
24
- end
25
-
26
- def current_user
27
- @current_user ||= session[:user] && self.class.user_model_class.find_by_id(session[:user])
28
- end
29
-
30
- def current_user=(new_user)
31
- session[:user] = new_user && new_user.id
32
- @current_user = new_user
33
- end
34
-
35
- def access_token
36
- cookie = cookies[LamAuth.cookie_id]
37
- LamAuth.valid_cookie?(cookie) && LamAuth.parse_cookie_to_hash(cookie)['access_token']
38
- end
39
-
40
- def login_from_cookie
41
- if logged_in?
42
- !access_token && self.current_user = nil
43
- else
44
- access_token && self.current_user = self.class.user_model_class.find_by_access_token(access_token)
45
- end
46
- end
47
-
48
- def login_required
49
- logged_in? || raise(LoginRequiredException)
50
- end
51
- end
52
- end
53
- end