surbase 0.0.5

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +70 -0
  6. data/Rakefile +1 -0
  7. data/lib/generators/surbase/install/install_generator.rb +70 -0
  8. data/lib/surbase.rb +137 -0
  9. data/lib/surbase/controller.rb +128 -0
  10. data/lib/surbase/model.rb +11 -0
  11. data/lib/surbase/version.rb +3 -0
  12. data/sample/surbase/.gitignore +19 -0
  13. data/sample/surbase/Gemfile +53 -0
  14. data/sample/surbase/README.rdoc +28 -0
  15. data/sample/surbase/Rakefile +6 -0
  16. data/sample/surbase/app/assets/images/.keep +0 -0
  17. data/sample/surbase/app/assets/javascripts/accounts.js.coffee +3 -0
  18. data/sample/surbase/app/assets/javascripts/application.js +16 -0
  19. data/sample/surbase/app/assets/stylesheets/accounts.css.scss +3 -0
  20. data/sample/surbase/app/assets/stylesheets/application.css +13 -0
  21. data/sample/surbase/app/controllers/accounts_controller.rb +3 -0
  22. data/sample/surbase/app/controllers/application_controller.rb +5 -0
  23. data/sample/surbase/app/controllers/concerns/.keep +0 -0
  24. data/sample/surbase/app/helpers/accounts_helper.rb +2 -0
  25. data/sample/surbase/app/helpers/application_helper.rb +2 -0
  26. data/sample/surbase/app/mailers/.keep +0 -0
  27. data/sample/surbase/app/models/.keep +0 -0
  28. data/sample/surbase/app/models/account.rb +2 -0
  29. data/sample/surbase/app/models/concerns/.keep +0 -0
  30. data/sample/surbase/app/models/provider_account.rb +2 -0
  31. data/sample/surbase/app/views/layouts/application.html.erb +14 -0
  32. data/sample/surbase/bin/bundle +3 -0
  33. data/sample/surbase/bin/rails +4 -0
  34. data/sample/surbase/bin/rake +4 -0
  35. data/sample/surbase/config.ru +4 -0
  36. data/sample/surbase/config/application.rb +23 -0
  37. data/sample/surbase/config/boot.rb +4 -0
  38. data/sample/surbase/config/environment.rb +5 -0
  39. data/sample/surbase/config/environments/development.rb +29 -0
  40. data/sample/surbase/config/environments/production.rb +80 -0
  41. data/sample/surbase/config/environments/test.rb +36 -0
  42. data/sample/surbase/config/initializers/backtrace_silencers.rb +7 -0
  43. data/sample/surbase/config/initializers/filter_parameter_logging.rb +4 -0
  44. data/sample/surbase/config/initializers/inflections.rb +16 -0
  45. data/sample/surbase/config/initializers/mime_types.rb +5 -0
  46. data/sample/surbase/config/initializers/secret_token.rb +12 -0
  47. data/sample/surbase/config/initializers/session_store.rb +3 -0
  48. data/sample/surbase/config/initializers/surbase.rb +7 -0
  49. data/sample/surbase/config/initializers/wrap_parameters.rb +14 -0
  50. data/sample/surbase/config/routes.rb +59 -0
  51. data/sample/surbase/db/migrate/20150312144839_create_accounts.rb +10 -0
  52. data/sample/surbase/db/migrate/20150313172400_create_provider_accounts.rb +12 -0
  53. data/sample/surbase/db/schema.rb +35 -0
  54. data/sample/surbase/db/seeds.rb +7 -0
  55. data/sample/surbase/lib/assets/.keep +0 -0
  56. data/sample/surbase/lib/tasks/.keep +0 -0
  57. data/sample/surbase/log/.keep +0 -0
  58. data/sample/surbase/public/404.html +58 -0
  59. data/sample/surbase/public/422.html +58 -0
  60. data/sample/surbase/public/500.html +57 -0
  61. data/sample/surbase/public/favicon.ico +0 -0
  62. data/sample/surbase/public/robots.txt +5 -0
  63. data/sample/surbase/test/controllers/.keep +0 -0
  64. data/sample/surbase/test/controllers/accounts_controller_test.rb +7 -0
  65. data/sample/surbase/test/fixtures/.keep +0 -0
  66. data/sample/surbase/test/helpers/.keep +0 -0
  67. data/sample/surbase/test/helpers/accounts_helper_test.rb +4 -0
  68. data/sample/surbase/test/integration/.keep +0 -0
  69. data/sample/surbase/test/mailers/.keep +0 -0
  70. data/sample/surbase/test/models/.keep +0 -0
  71. data/sample/surbase/test/models/account_test.rb +7 -0
  72. data/sample/surbase/test/models/provider_account_test.rb +7 -0
  73. data/sample/surbase/test/test_helper.rb +15 -0
  74. data/sample/surbase/vendor/assets/javascripts/.keep +0 -0
  75. data/sample/surbase/vendor/assets/stylesheets/.keep +0 -0
  76. data/surbase.gemspec +23 -0
  77. metadata +147 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d03849b3405fe0e36d1ed421b04d2a0b62a9bcd
4
+ data.tar.gz: 1eb7503667a3af9c7a12f5684ac0eaf2f37f95be
5
+ SHA512:
6
+ metadata.gz: a4b51063f2652c11d14ae68242626677d8c605cf10a0442ed9517c2eb3eed8fda1b1c19f094d8ecfc02cb69c3dae0a4d0144a722fe6b44dc7f10fd8583de0426
7
+ data.tar.gz: a2a3b25ceb9f98d9195dad797a2d219a4bf69da998392a0200e704248a3745716977fe58e5cd687d0b8d8a69c1a2c6025ef384c139a623af0816842fa09c5eae
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in surbase.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 liveralmask
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,70 @@
1
+ # Surbase
2
+
3
+ Base system for web services.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'surbase'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install surbase
18
+
19
+ ## Usage
20
+
21
+ ### 1. Add Gemfile
22
+
23
+ gem "surbase"
24
+ gem "omniauth"
25
+ gem "omniauth-twitter" # Optional
26
+ gem "omniauth-facebook" # Optional
27
+ gem "omniauth-github" # Optional
28
+
29
+ ### 2. Bundle install
30
+
31
+ bundle install
32
+
33
+ ### 3. Install custom generator
34
+
35
+ rails generate surbase:install
36
+
37
+ ### 4. Edit config/surbase_secrets.rb
38
+
39
+ vi config/surbase_secrets.rb
40
+
41
+ ### 5. Edit config/initializers/surbase.rb
42
+
43
+ vi config/initializers/surbase.rb
44
+
45
+ ### 6. Add config/routes.rb
46
+
47
+ get "login/:provider" => "accounts#login"
48
+ get "auth/:provider/callback" => "accounts#auth_callback"
49
+
50
+ ### 7. Migrate database
51
+
52
+ rake db:migrate
53
+
54
+ ### 8. Start server
55
+
56
+ rails server
57
+
58
+ ### 9. Access URL
59
+
60
+ http://localhost:3000/login/twitter
61
+ http://localhost:3000/login/facebook
62
+ http://localhost:3000/login/github
63
+
64
+ ## Contributing
65
+
66
+ 1. Fork it ( http://github.com/<my-github-username>/surbase/fork )
67
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
68
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
69
+ 4. Push to the branch (`git push origin my-new-feature`)
70
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,70 @@
1
+ require "rails"
2
+ require "surbase"
3
+
4
+ module Surbase
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ def generate
7
+ file_path = "app/controllers/accounts_controller.rb"
8
+ if ! File.exists?( file_path )
9
+ Command.execute( "rails generate controller accounts" ).output
10
+
11
+ open( file_path, "wb" ){|f|
12
+ f.puts <<EOS
13
+ class AccountsController < ApplicationController
14
+ include Surbase::AccountsController
15
+
16
+ protected
17
+ def result_api( status )
18
+ cookie( :account_info, status.values, 30.days.from_now ) if status.values.key?( :account_id )
19
+
20
+ redirect_to "/"
21
+ end
22
+ end
23
+ EOS
24
+ }
25
+ end
26
+
27
+ file_path = "app/models/account.rb"
28
+ Command.execute( "rails generate model account provider_id:string login_key:string" ).output if ! File.exists?( file_path )
29
+
30
+ file_path = "app/models/provider_account.rb"
31
+ Command.execute( "rails generate model provider_account account_id:integer name:string icon:string encrypted_access_token:string" ).output if ! File.exists?( file_path )
32
+
33
+ file_path = "config/initializers/surbase.rb"
34
+ if ! File.exists?( file_path )
35
+ open( file_path, "wb" ){|f|
36
+ f.puts <<EOS
37
+ Surbase::Config.setup do
38
+ prefix ""
39
+
40
+ # provider :twitter
41
+ # provider :facebook
42
+ # provider :github
43
+ end
44
+ EOS
45
+ }
46
+ end
47
+
48
+ file_path = "config/surbase_secrets.rb"
49
+ if ! File.exists?( file_path )
50
+ open( file_path, "wb" ){|f|
51
+ f.puts <<EOS
52
+ Surbase::Secrets.setup do
53
+ set( :CIPHER_NAME, "AES-256-CBC" )
54
+
55
+ # set( :TWITTER_KEY, "" )
56
+ # set( :TWITTER_SECRET, "" )
57
+
58
+ # set( :FACEBOOK_KEY, "" )
59
+ # set( :FACEBOOK_SECRET, "" )
60
+
61
+ # set( :GITHUB_KEY, "" )
62
+ # set( :GITHUB_SECRET, "" )
63
+ end
64
+ EOS
65
+ }
66
+ Command.execute( %Q(echo "\n#{file_path}" >> .gitignore) )
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,137 @@
1
+ require "surbase/version"
2
+ require "surbase/controller"
3
+
4
+ require "open3"
5
+ require "base64"
6
+
7
+ module Surbase
8
+ class Command
9
+ def self.execute( info )
10
+ Command.new.execute( info )
11
+ end
12
+
13
+ attr_accessor :info, :out, :err, :status
14
+
15
+ def execute( info )
16
+ if ! info.instance_of?( Hash )
17
+ info = {
18
+ :cmd => info
19
+ }
20
+ else
21
+ return nil if ! info.key?( :cmd )
22
+ end
23
+
24
+ @out, @err, status = Open3.capture3( info[ :cmd ], { :stdin_data => info[ :stdin_data ] } )
25
+ @status = status.exitstatus
26
+ @info = info
27
+ self
28
+ end
29
+
30
+ def output
31
+ puts @info[ :cmd ]
32
+ puts @out if ! @out.empty?
33
+ $stderr.puts @err if ! @err.empty?
34
+ end
35
+ end
36
+
37
+ class Status
38
+ Success = "0"
39
+ Unknown = "-1"
40
+ ModelSaveError = "-100"
41
+
42
+ @@status = {
43
+ Success => "Success",
44
+ Unknown => "Unknown Error",
45
+ ModelSaveError => "Model Save Error",
46
+ }
47
+
48
+ def self.msg( code )
49
+ @@status.key?( code ) ? @@status[ code ] : "Unknown Code=#{code}"
50
+ end
51
+
52
+ def self.set( code, msg )
53
+ @@status[ code ] = msg
54
+ Status.new( code )
55
+ end
56
+
57
+ attr_accessor :code, :values
58
+
59
+ def initialize( code = Unknown, values = {} )
60
+ @code = code
61
+ @values = values
62
+ end
63
+
64
+ def msg
65
+ Status.msg( @code )
66
+ end
67
+ end
68
+
69
+ class Cipher
70
+ def initialize( name )
71
+ @cipher = OpenSSL::Cipher.new( name )
72
+ end
73
+
74
+ def encode( value )
75
+ Base64.urlsafe_encode64( value )
76
+ end
77
+
78
+ def decode( encoded_value )
79
+ Base64.urlsafe_decode64( encoded_value )
80
+ end
81
+
82
+ def encrypt( data, pass )
83
+ @cipher.encrypt
84
+ @cipher.pkcs5_keyivgen( pass )
85
+ encode( @cipher.update( data ) + @cipher.final )
86
+ end
87
+
88
+ def decrypt( data, pass )
89
+ @cipher.decrypt
90
+ @cipher.pkcs5_keyivgen( pass )
91
+ @cipher.update( decode( data ) ) + @cipher.final
92
+ end
93
+ end
94
+
95
+ class Secrets
96
+ def self.set( key, value )
97
+ ENV[ key.to_s ] = value.to_s
98
+ end
99
+
100
+ def self.get( key )
101
+ ENV[ key.to_s ]
102
+ end
103
+
104
+ def self.setup( &block )
105
+ module_eval( &block )
106
+ end
107
+ end
108
+
109
+ class Config
110
+ @@prefix = ""
111
+ @@providers = []
112
+
113
+ def self.prefix( prefix )
114
+ @@prefix = prefix
115
+ end
116
+
117
+ def self.setup( &block )
118
+ require "#{Rails.root}/config/surbase_secrets.rb"
119
+
120
+ module_eval( &block )
121
+
122
+ Rails.application.config.middleware.use OmniAuth::Builder do
123
+ @@providers.each{|provider|
124
+ provider provider[ :provider ], provider[ :key ], provider[ :secret ]
125
+ }
126
+ end
127
+ end
128
+
129
+ def self.provider( provider )
130
+ @@providers.push({
131
+ :provider => provider,
132
+ :key => Secrets.get( "#{@@prefix}#{provider.upcase}_KEY" ),
133
+ :secret => Secrets.get( "#{@@prefix}#{provider.upcase}_SECRET" ),
134
+ })
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,128 @@
1
+ require "surbase/model"
2
+
3
+ module Surbase
4
+ module Controller
5
+ def initialize
6
+ super
7
+
8
+ @cipher = Cipher.new( Secrets.get( :CIPHER_NAME ) )
9
+ end
10
+
11
+ protected
12
+ def result_hash( status )
13
+ {
14
+ :status => {
15
+ :code => status.code,
16
+ :msg => status.msg,
17
+ :values => status.values,
18
+ }
19
+ }
20
+ end
21
+
22
+ def result_api( status )
23
+ render :json => result_hash( status )
24
+ end
25
+
26
+ def cookie( key, value, expires )
27
+ cookies[ key ] = { :value => value, :expires => expires }
28
+ end
29
+
30
+ def to_json( object )
31
+ JSON.generate( object )
32
+ end
33
+
34
+ def from_json( json )
35
+ JSON.parse( json )
36
+ end
37
+
38
+ def create_key( salt )
39
+ Digest::SHA512::hexdigest( salt )
40
+ end
41
+
42
+ def create_key_random
43
+ now = Time.now.to_i
44
+ create_key( [
45
+ now,
46
+ rand( now ),
47
+ rand( now ),
48
+ rand( now )
49
+ ].join( "_" ) )
50
+ end
51
+
52
+ def encrypt_json( access_token, pass )
53
+ @cipher.encrypt( to_json( access_token ), pass )
54
+ end
55
+
56
+ def decrypt_json( encrypted_access_token, pass )
57
+ from_json( @cipher.decrypt( encrypted_access_token, pass ) )
58
+ end
59
+
60
+ def error_status( code, exception )
61
+ status = Status.new( code, [ exception.message ] )
62
+ status.values.concat( exception.backtrace ) if ! Rails.env.production?
63
+ status
64
+ end
65
+ end
66
+
67
+ module AccountsController
68
+ include Controller
69
+
70
+ def login
71
+ redirect_to "/auth/#{params[ :provider ]}"
72
+ end
73
+
74
+ def auth_callback
75
+ auth = request.env[ "omniauth.auth" ]
76
+ result_api( login_callback({
77
+ :auth => auth,
78
+ :provider => auth[ "provider" ],
79
+ :uid => auth[ "uid" ],
80
+ :provider_id => %Q(#{auth[ "provider" ]}\t#{auth[ "uid" ]}),
81
+ :name => auth[ "info" ][ "name" ],
82
+ :icon => auth[ "info" ][ "image" ],
83
+ :access_token => {
84
+ :token => auth[ "credentials" ][ "token" ],
85
+ :secret => auth[ "credentials" ][ "secret" ],
86
+ },
87
+ :login_key => create_key_random
88
+ }) )
89
+ end
90
+
91
+ protected
92
+ def login_callback( info )
93
+ status = Status.new
94
+
95
+ account = nil
96
+ ActiveRecord::Base.transaction do
97
+ account_data = {
98
+ :provider_id => info[ :provider_id ],
99
+ :login_key => info[ :login_key ],
100
+ }
101
+ account = Model.load( ::Account, [ "provider_id=?", account_data[ :provider_id ] ], account_data )
102
+ account.save!
103
+
104
+ provider_account_data = {
105
+ :account_id => account.id,
106
+ :name => info[ :name ],
107
+ :icon => info[ :icon ],
108
+ :encrypted_access_token => encrypt_json( info[ :access_token ], info[ :login_key ] ),
109
+ }
110
+ provider_account = Model.load( ::ProviderAccount, [ "account_id=?", account.id ], provider_account_data )
111
+ provider_account.save!
112
+ end
113
+ status.code = Status::Success
114
+ status.values = {
115
+ :provider_info => {
116
+ :provider => info[ :provider ],
117
+ :name => info[ :name ],
118
+ :icon => info[ :icon ],
119
+ },
120
+ :account_id => @cipher.encrypt( @cipher.encode( account.id.to_s ), info[ :login_key ] ),
121
+ :login_key => info[ :login_key ],
122
+ }
123
+ status
124
+ rescue => e
125
+ error_status( Status::ModelSaveError, e )
126
+ end
127
+ end
128
+ end