surbase 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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