lam_auth 0.1.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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in lam_auth.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,42 @@
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
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/lam_auth.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lam_auth/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "lam_auth"
7
+ s.version = LamAuth::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Max Macovsky", "Anton Platonov"]
10
+ s.email = ["robotector@gmail.com", "platosha@lookatme.ru"]
11
+ s.homepage = "http://github.com/macovsky/lam_auth"
12
+ s.summary = %q{Аутентификация для спецпроектов Lookatme}
13
+ s.description = %q{}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,19 @@
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
@@ -0,0 +1,28 @@
1
+ module LamAuth
2
+ module Generators
3
+ class LamAuthGenerator < Rails::Generators::NamedBase
4
+ namespace "lam_auth"
5
+ source_root File.expand_path("../../templates", __FILE__)
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
14
+
15
+ def copy_xd_receiver
16
+ copy_file 'xd_receiver.html', 'public/xd_receiver.html'
17
+ end
18
+
19
+ def copy_yml
20
+ copy_file 'lam_auth.yml', 'config/lam_auth.yml'
21
+ end
22
+
23
+ def show_readme
24
+ readme "README" if behavior == :invoke
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+
2
+ 888 888 888
3
+ 888 http://github.com/macovsky/lam_auth 888 888
4
+ 888 888 888
5
+ 888 8888b. 88888b.d88b. 8888b. 888 888 888888 88888b.
6
+ 888 "88b 888 "888 "88b "88b 888 888 888 888 "88b
7
+ 888 .d888888 888 888 888 .d888888 888 888 888 888 888
8
+ 888 888 888 888 888 888 888 888 Y88b 888 Y88b. 888 888
9
+ 888 "Y888888 888 888 888 88888888 "Y888888 "Y88888 "Y888 888 888
@@ -0,0 +1,13 @@
1
+ # return_url можно не указывать, если это дефолтный http://:app-domain/xd_receiver.html
2
+
3
+ development: &dev
4
+ app_id:
5
+ secret:
6
+
7
+ test:
8
+ <<: *dev
9
+
10
+ production:
11
+ app_id:
12
+ secret:
13
+ return_url:
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE HTML>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title></title>
6
+ <script type="text/javascript">
7
+ window.opener.LAM.successLogin(window.location.hash.substring(1));
8
+ </script>
9
+ </head>
10
+ <body><p>Loading...</p>
11
+ </body>
12
+ </html>
13
+
14
+
15
+
@@ -0,0 +1,45 @@
1
+ module LamAuth
2
+ module ControllerExtensions
3
+ def lam_auth_for(klass)
4
+ class_inheritable_accessor :model_class
5
+ self.model_class = klass.to_s.classify.constantize
6
+ helper_method(:current_user, :logged_in?)
7
+ before_filter :login_from_cookie
8
+
9
+ include InstanceMethods
10
+ protected :logged_in?, :current_user, :current_user=, :auth_token, :login_from_cookie, :login_required
11
+ end
12
+
13
+ module InstanceMethods
14
+ def logged_in?
15
+ !!current_user
16
+ end
17
+
18
+ def current_user
19
+ @current_user ||= session[:user] && model_class.find_by_id(session[:user])
20
+ end
21
+
22
+ def current_user=(new_user)
23
+ session[:user] = new_user && new_user.id
24
+ @current_user = new_user
25
+ end
26
+
27
+ def auth_token
28
+ cookie = cookies[LamAuth.cookie_id]
29
+ @auth_token ||= LamAuth.valid_cookie?(cookie) && LamAuth.parse_cookie_to_hash(cookie)['access_token']
30
+ end
31
+
32
+ def login_from_cookie
33
+ if logged_in?
34
+ !auth_token && self.current_user = nil
35
+ else
36
+ auth_token && self.current_user = model_class.find_by_auth_token(auth_token)
37
+ end
38
+ end
39
+
40
+ def login_required
41
+ logged_in? || raise(LoginRequiredException)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ module LamAuth
2
+ module Helpers
3
+ def lam_auth_include_tag
4
+ javascript_include_tag(LamAuth.url + "/api/js/LAM.Login.js")
5
+ end
6
+
7
+ def lam_auth_init_tag(options = {})
8
+ options.reverse_merge!(
9
+ :app_id => LamAuth.config['app_id'],
10
+ :panel_node_id => 'lam-root',
11
+ :fixed => false
12
+ )
13
+ options.reverse_merge!(:xd_receiver_url => LamAuth.config['return_url']) if LamAuth.config['return_url']
14
+
15
+ javascript_tag("LAM.init({#{options.map{|k, v| "#{k.to_s.camelize(:lower)}: #{v.inspect}"}.join(",\n")}});")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,51 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ module LamAuth
4
+ module Model
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)
10
+ end
11
+
12
+ module ClassMethods
13
+ def find_by_auth_token(auth_token)
14
+ Rails.logger.info("Trying to authorize a token #{auth_token.inspect} ")
15
+
16
+ lam_uri = LamAuth.uri
17
+ http = Net::HTTP.new(lam_uri.host, lam_uri.port)
18
+ response, body = http.get("#{lam_uri.path}/users/me", {'Authorization' => "Token token=\"#{auth_token}\""})
19
+ if response.code == "200"
20
+ data = ActiveSupport::JSON.decode(body)
21
+ Rails.logger.info("...success: #{data.inspect}")
22
+ create_or_update_by_auth_data(data)
23
+ end
24
+ rescue Net::ProtoRetriableError => detail
25
+ Rails.logger.info("...failed!")
26
+ Rails.logger.info(detail)
27
+ nil
28
+ end
29
+
30
+ def create_or_update_by_auth_data(data)
31
+ user = find_or_initialize_by_login(data['login'])
32
+ user.update_attributes data.slice(*%w{email first_name last_name}).merge(
33
+ 'userpic' => data['userpic']['icon'],
34
+ 'profile' => data.except(*%w{login email first_name last_name userpic})
35
+ )
36
+ user
37
+ end
38
+ end
39
+
40
+ def name
41
+ [first_name, last_name].select(&:present?).join(" ")
42
+ end
43
+
44
+ def userpic(version = :icon)
45
+ pic = read_attribute(:userpic)
46
+ return nil if pic.blank?
47
+ pic.sub(/user-userpic-\w+/, "user-userpic-#{version}")
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module LamAuth
2
+ VERSION = "0.1.0"
3
+ end
data/lib/lam_auth.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'rack/utils'
2
+ require 'digest/md5'
3
+
4
+ require 'lam_auth/controller_extensions'
5
+ require 'lam_auth/helpers'
6
+ require 'lam_auth/model'
7
+ ActionController::Base.extend(LamAuth::ControllerExtensions)
8
+ ActionController::Base.helper(LamAuth::Helpers)
9
+
10
+ module LamAuth
11
+ class LoginRequiredException < Exception
12
+ end
13
+
14
+ class << self
15
+ def config
16
+ @config ||= YAML.load_file(Rails.root.join("config/lam_auth.yml"))[Rails.env]
17
+ end
18
+
19
+ def url
20
+ "http://www.lookatme.ru"
21
+ end
22
+
23
+ def signup_url
24
+ "#{url}/signup"
25
+ end
26
+
27
+ def uri
28
+ URI.parse(url)
29
+ end
30
+
31
+ def cookie_id
32
+ "lam_#{config['app_id']}"
33
+ end
34
+
35
+ def valid_cookie?(data)
36
+ valid_hash?(parse_cookie_to_hash(data))
37
+ end
38
+
39
+ def parse_cookie_to_hash(data)
40
+ Rack::Utils.parse_query(Rack::Utils.unescape(data.to_s.gsub('"', '')))
41
+ end
42
+
43
+ def valid_hash?(hash)
44
+ Digest::MD5.hexdigest(hash.except('sig').sort.map{|v| v.join('=')}.join + LamAuth.config['secret']) == hash['sig']
45
+ end
46
+ end
47
+ end
48
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lam_auth
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Max Macovsky
14
+ - Anton Platonov
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-04-13 00:00:00 +04:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: ""
24
+ email:
25
+ - robotector@gmail.com
26
+ - platosha@lookatme.ru
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - .gitignore
35
+ - Gemfile
36
+ - README.rdoc
37
+ - Rakefile
38
+ - lam_auth.gemspec
39
+ - lib/generators/active_record/lam_auth_generator.rb
40
+ - lib/generators/active_record/templates/migration.rb
41
+ - lib/generators/lam_auth/helpers.rb
42
+ - lib/generators/lam_auth/lam_auth_generator.rb
43
+ - lib/generators/templates/README
44
+ - lib/generators/templates/lam_auth.yml
45
+ - lib/generators/templates/xd_receiver.html
46
+ - lib/lam_auth.rb
47
+ - lib/lam_auth/controller_extensions.rb
48
+ - lib/lam_auth/helpers.rb
49
+ - lib/lam_auth/model.rb
50
+ - lib/lam_auth/version.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/macovsky/lam_auth
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.6.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: !binary |
85
+ 0JDRg9GC0LXQvdGC0LjRhNC40LrQsNGG0LjRjyDQtNC70Y8g0YHQv9C10YbQ
86
+ v9GA0L7QtdC60YLQvtCyIExvb2thdG1l
87
+
88
+ test_files: []
89
+