remotty-rails 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +18 -0
- data/LICENSE.txt +22 -0
- data/README.md +234 -0
- data/Rakefile +2 -0
- data/app/controllers/remotty/base_application_controller.rb +36 -0
- data/app/controllers/remotty/users/base_controller.rb +16 -0
- data/app/controllers/remotty/users/confirmations_controller.rb +25 -0
- data/app/controllers/remotty/users/omniauth_callbacks_controller.rb +102 -0
- data/app/controllers/remotty/users/passwords_controller.rb +47 -0
- data/app/controllers/remotty/users/registrations_controller.rb +132 -0
- data/app/controllers/remotty/users/sessions_controller.rb +48 -0
- data/app/models/remotty/base_user.rb +83 -0
- data/app/serializers/remotty/user_serializer.rb +30 -0
- data/config/locales/ko.yml +58 -0
- data/lib/generators/remotty/rails/install_generator.rb +68 -0
- data/lib/generators/remotty/rails/templates/add_column_to_users.rb +42 -0
- data/lib/generators/remotty/rails/templates/auth_token.rb +22 -0
- data/lib/generators/remotty/rails/templates/create_auth_tokens.rb +28 -0
- data/lib/generators/remotty/rails/templates/create_oauth_authentications.rb +28 -0
- data/lib/generators/remotty/rails/templates/oauth_authentication.rb +18 -0
- data/lib/generators/remotty/rails/templates/paperclip_hash.rb +1 -0
- data/lib/generators/remotty/rails/templates/user_serializer.rb +3 -0
- data/lib/remotty/rails.rb +8 -0
- data/lib/remotty/rails/authentication.rb +6 -0
- data/lib/remotty/rails/authentication/json_auth_failure.rb +29 -0
- data/lib/remotty/rails/authentication/strategies/token_header_authenticable.rb +71 -0
- data/lib/remotty/rails/engine.rb +72 -0
- data/lib/remotty/rails/version.rb +5 -0
- data/rdoc.sh +3 -0
- data/remotty-rails.gemspec +35 -0
- metadata +231 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0775052ff14b274bde5cb2946958851c7679d547
|
4
|
+
data.tar.gz: 9e29cbf6c8d47dfa73ae6717b985715a790ab400
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: daba021256deb24ad4492d4f12c9ff94b96d616c989cf8076227c50e432aa990b73a12a49adc04a8619bcd28e98bc13f16bd7923b78138e84b252e8999f48b30
|
7
|
+
data.tar.gz: 0a3b34fef53c7a60239b97f0cc47175d371c3092fca263d88cf7a3041832297b9a8f12160a6580b2b44b73861f82310877f79ccf1ca4089a26c44f084e683ca7
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
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
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
|
24
|
+
.idea
|
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in remotty-rails.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'rack-cors', :require => 'rack/cors'
|
7
|
+
gem 'active_model_serializers'
|
8
|
+
|
9
|
+
# Authentication
|
10
|
+
gem 'devise'
|
11
|
+
gem 'omniauth-facebook'
|
12
|
+
gem 'omniauth-twitter'
|
13
|
+
|
14
|
+
# File upload
|
15
|
+
gem 'paperclip'
|
16
|
+
gem 'open_uri_redirections'
|
17
|
+
gem 'rmagick', require: false
|
18
|
+
gem 'fog'
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Chungsub Kim
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
# remotty-rails
|
2
|
+
|
3
|
+
AngularJS + Rails API를 사용할 때 기본적인 셋팅을 도와주어 빠른 초기 셋팅을 가능하게 합니다.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
### 적용사항
|
8
|
+
|
9
|
+
* header의 token을 이용한 인증처리
|
10
|
+
* auth_token model 추가
|
11
|
+
* facebook/twitter oauth login
|
12
|
+
* oauth_authentication model 추가
|
13
|
+
* join
|
14
|
+
* email
|
15
|
+
* oauth (facebook/twitter)
|
16
|
+
* email이 없는 경우도 처리
|
17
|
+
* custom devise controller
|
18
|
+
* full customizing
|
19
|
+
* json response
|
20
|
+
* sessions controller
|
21
|
+
* registrations controller
|
22
|
+
* confirmations controller
|
23
|
+
* passwords controller
|
24
|
+
* omniauth_callbacks controller
|
25
|
+
* user model
|
26
|
+
* use avatar for profile image
|
27
|
+
* use paperclip for attachment
|
28
|
+
* use serializer for json response
|
29
|
+
* CORS
|
30
|
+
* no cookie/no session
|
31
|
+
|
32
|
+
### Token Based Header Authenticable
|
33
|
+
|
34
|
+
header에 email과 token을 전달하여 인증을 처리함
|
35
|
+
|
36
|
+
* X-Auth-Email : e-mail
|
37
|
+
* X-Auth-Token : auth token
|
38
|
+
* X-Auth-Device : source (web(default)/ios/android/...)
|
39
|
+
* X-Auth-Device-Info : source info (ip(default)/...)
|
40
|
+
|
41
|
+
### JSON format
|
42
|
+
|
43
|
+
* disable root globally
|
44
|
+
* failure default syntax
|
45
|
+
|
46
|
+
```json
|
47
|
+
{
|
48
|
+
"error":{
|
49
|
+
"code":"ERROR_CODE",
|
50
|
+
"message":"error message"
|
51
|
+
}
|
52
|
+
}
|
53
|
+
```
|
54
|
+
|
55
|
+
### Controller Helper
|
56
|
+
|
57
|
+
* render_error helper
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
def render_error(code = 'ERROR', message = '', status = 400)
|
61
|
+
render json: {
|
62
|
+
error: {
|
63
|
+
code: code,
|
64
|
+
message: message
|
65
|
+
}
|
66
|
+
}, :status => status
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
|
71
|
+
## Library
|
72
|
+
|
73
|
+
remotty-rails에서 사용중인 라이브러리 입니다.
|
74
|
+
|
75
|
+
* `rails-api`
|
76
|
+
* Rails for API only application (https://github.com/rails-api/rails-api)
|
77
|
+
* `active_model_serializers`
|
78
|
+
* JSON serialization of objects (https://github.com/rails-api/active_model_serializers)
|
79
|
+
* `paperclip`+`rmagick`+`fog`+`httparty`
|
80
|
+
* Easy file attachment management (https://github.com/thoughtbot/paperclip)
|
81
|
+
* `devise`
|
82
|
+
* Flexible authentication solution (https://github.com/plataformatec/devise)
|
83
|
+
|
84
|
+
|
85
|
+
## Installation
|
86
|
+
|
87
|
+
* Create Rails API Project
|
88
|
+
|
89
|
+
```sh
|
90
|
+
$ gem install rails -v 4.0.5 --no-ri --no-rdoc
|
91
|
+
$ rails-api new {{project}} --skip-test-unit --skip-sprockets
|
92
|
+
```
|
93
|
+
|
94
|
+
* Add this line to your application's Gemfile:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
gem 'remotty-rails'
|
98
|
+
gem 'devise'
|
99
|
+
gem 'omniauth-facebook'
|
100
|
+
gem 'omniauth-twitter'
|
101
|
+
gem 'paperclip'
|
102
|
+
```
|
103
|
+
|
104
|
+
* And then execute:
|
105
|
+
|
106
|
+
```sh
|
107
|
+
$ bundle
|
108
|
+
```
|
109
|
+
|
110
|
+
* install devise
|
111
|
+
|
112
|
+
```sh
|
113
|
+
$ rails generate devise:install
|
114
|
+
$ rails generate devise User
|
115
|
+
```
|
116
|
+
|
117
|
+
* install remotty-rails
|
118
|
+
|
119
|
+
`initializers/devise.rb`에서 `config.secret_key` 주석 지우고 작업
|
120
|
+
|
121
|
+
```
|
122
|
+
$ rails generate remotty:rails:install
|
123
|
+
$ rake db:migrate
|
124
|
+
```
|
125
|
+
|
126
|
+
* `config/routes.rb` update
|
127
|
+
|
128
|
+
`devise_for :users`를 지우고 추가함
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
devise_for :users,
|
132
|
+
:path => 'api/v1/session',
|
133
|
+
:path_names => {
|
134
|
+
sign_in: 'login',
|
135
|
+
sign_out: 'logout'
|
136
|
+
},
|
137
|
+
:controllers => { sessions: 'remotty/users/sessions',
|
138
|
+
registrations: 'remotty/users/registrations',
|
139
|
+
confirmations: 'remotty/users/confirmations',
|
140
|
+
passwords: 'remotty/users/passwords',
|
141
|
+
omniauth_callbacks: 'remotty/users/omniauth_callbacks'}
|
142
|
+
```
|
143
|
+
|
144
|
+
## Recommend Setting
|
145
|
+
|
146
|
+
### 유용한 Gemfile
|
147
|
+
|
148
|
+
`Gemfile` update
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
group :development do
|
152
|
+
gem 'thin'
|
153
|
+
gem 'annotate'
|
154
|
+
gem 'better_errors'
|
155
|
+
gem 'binding_of_caller'
|
156
|
+
gem 'letter_opener'
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
### sendmail test
|
161
|
+
|
162
|
+
`development.rb` update
|
163
|
+
`letter_opener`는 gem 추가해야함 `gem 'letter_opener'`
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
config.action_mailer.default_url_options = { host: 'localhost:9000' }
|
167
|
+
config.action_mailer.delivery_method = :letter_opener
|
168
|
+
```
|
169
|
+
|
170
|
+
### custom mail view
|
171
|
+
|
172
|
+
|
173
|
+
`views/devise/mailer/confirmation_instructions.html.erb` create
|
174
|
+
`views/devise/mailer/reset_password_instructions.html.erb` create
|
175
|
+
|
176
|
+
|
177
|
+
### token 유효기간 변경
|
178
|
+
|
179
|
+
`initializers/devise.rb` update
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
config.remember_for = 2.weeks
|
183
|
+
```
|
184
|
+
|
185
|
+
### omniauth setting
|
186
|
+
|
187
|
+
`devise.rb` update
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
config.omniauth :facebook,
|
191
|
+
Settings.omniauth.facebook.app_id,
|
192
|
+
Settings.omniauth.facebook.app_secret,
|
193
|
+
{
|
194
|
+
scope: 'email',
|
195
|
+
image_size: 'large',
|
196
|
+
provider_ignores_state: true
|
197
|
+
}
|
198
|
+
config.omniauth :twitter,
|
199
|
+
Settings.omniauth.twitter.consumer_key,
|
200
|
+
Settings.omniauth.twitter.consumer_secret, {
|
201
|
+
:image_size => 'original',
|
202
|
+
:authorize_params => {
|
203
|
+
:force_login => true
|
204
|
+
},
|
205
|
+
:setup => lambda do |env|
|
206
|
+
req = Rack::Request.new(env)
|
207
|
+
req.session.options[:cookie_only] = true
|
208
|
+
req.session.options[:defer] = false
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
212
|
+
### devise parameter sanitizer
|
213
|
+
|
214
|
+
user model에 column 추가시 `application_controller.rb` 파일에 추가함
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
class ApplicationController < ActionController::API
|
218
|
+
|
219
|
+
protected
|
220
|
+
|
221
|
+
def configure_permitted_parameters
|
222
|
+
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :current_password, :avatar) }
|
223
|
+
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :avatar, :password, :password_confirmation, :current_password) }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
```
|
227
|
+
|
228
|
+
## Contributing
|
229
|
+
|
230
|
+
1. Fork it ( https://github.com/remotty/remotty-rails/fork )
|
231
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
232
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
233
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
234
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Remotty::BaseApplicationController
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
before_action :authenticate_user!
|
6
|
+
before_action :configure_permitted_parameters, if: :devise_controller?
|
7
|
+
|
8
|
+
# To resolve the following error: ActionController::UnknownFormat
|
9
|
+
include ActionController::StrongParameters
|
10
|
+
|
11
|
+
# To resolve the following error: undefined method `respond_to'
|
12
|
+
# http://railscasts.com/episodes/348-the-rails-api-gem?language=ko&view=asciicast
|
13
|
+
include ActionController::MimeResponds
|
14
|
+
|
15
|
+
# To resolve the following error: undefined method `default_render'
|
16
|
+
# https://github.com/rails-api/rails-api/issues/93
|
17
|
+
include ActionController::ImplicitRender
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def render_error(code = 'ERROR', message = '', status = 400)
|
23
|
+
render json: {
|
24
|
+
error: {
|
25
|
+
code: code,
|
26
|
+
message: message
|
27
|
+
}
|
28
|
+
}, :status => status
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure_permitted_parameters
|
32
|
+
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, :email, :password, :current_password, :avatar) }
|
33
|
+
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:name, :avatar, :password, :password_confirmation, :current_password) }
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# base user controller
|
2
|
+
#
|
3
|
+
module Remotty::Users::BaseController
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
# auth_source 정보 추출 (앱 확장성 고려)
|
9
|
+
def auth_source
|
10
|
+
{
|
11
|
+
source: request.headers['X-Auth-Device'] || 'web',
|
12
|
+
info: request.headers['X-Auth-Device-Info'] || request.remote_ip
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Remotty::Users::ConfirmationsController < Devise::ConfirmationsController
|
2
|
+
include Remotty::Users::BaseController
|
3
|
+
|
4
|
+
# POST /resource/confirmation
|
5
|
+
# 토큰을 이용해 이메일 인증 확인
|
6
|
+
# 이미 사용한 토큰이거나 잘못된 경우는 에러 반환
|
7
|
+
#
|
8
|
+
# ==== return
|
9
|
+
# * +success+ - no_content
|
10
|
+
# * +failure+ - unauthorized with error message
|
11
|
+
#
|
12
|
+
def show
|
13
|
+
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
14
|
+
yield resource if block_given?
|
15
|
+
|
16
|
+
if resource.errors.empty?
|
17
|
+
render nothing: true, status: :no_content
|
18
|
+
else
|
19
|
+
render_error 'UNAUTHORIZED',
|
20
|
+
resource.errors.full_messages.first,
|
21
|
+
:unauthorized
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class Remotty::Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
2
|
+
include Remotty::Users::BaseController
|
3
|
+
include ActionController::Flash
|
4
|
+
|
5
|
+
# omniauth callback 처리
|
6
|
+
# 정보에 따라 유저를 만들던가 연결하던가 추가 정보를 입력받도록 에러를 리턴함
|
7
|
+
#
|
8
|
+
def all
|
9
|
+
# omniauth에서 생성한 session 제거
|
10
|
+
session.options[:skip] = true
|
11
|
+
response.headers['Set-Cookie'] = 'rack.session=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT'
|
12
|
+
|
13
|
+
auth = request.env['omniauth.auth']
|
14
|
+
user = from_omniauth(auth)
|
15
|
+
@ret = {}
|
16
|
+
|
17
|
+
if user && user.persisted?
|
18
|
+
sign_in(:user, user, store: false)
|
19
|
+
token = user.generate_auth_token!(auth_source)
|
20
|
+
@ret = user.with_token(token)
|
21
|
+
elsif user && user.errors.size > 0
|
22
|
+
@ret = {
|
23
|
+
error: {
|
24
|
+
code: 'OAUTH_LOGIN_ERROR_EMAIL_INVALID',
|
25
|
+
message: user.errors.full_messages.first,
|
26
|
+
data: {
|
27
|
+
oauth: {
|
28
|
+
credentials: auth[:credentials],
|
29
|
+
provider: auth[:provider],
|
30
|
+
uid: auth[:uid],
|
31
|
+
info: {
|
32
|
+
name: auth[:info][:name],
|
33
|
+
image: auth[:info][:image]
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
else
|
40
|
+
@ret = {
|
41
|
+
error: {
|
42
|
+
code: 'OAUTH_LOGIN_ERROR',
|
43
|
+
message: 'require provider & uid!!'
|
44
|
+
}
|
45
|
+
}
|
46
|
+
@ret[:error][:data] = user if user
|
47
|
+
end
|
48
|
+
|
49
|
+
render :inline => "<script>window.opener.oauthCallback(#{@ret.to_json}); window.close();</script>"
|
50
|
+
end
|
51
|
+
|
52
|
+
def failure
|
53
|
+
@ret = {
|
54
|
+
error: {
|
55
|
+
code: OmniAuth::Utils.camelize(failed_strategy.name),
|
56
|
+
message: failure_message
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
render :inline => "<script>window.opener.oauthCallback(#{@ret.to_json}); window.close();</script>"
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :facebook, :all
|
64
|
+
alias_method :twitter, :all
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# omniauth callback 분석
|
69
|
+
def from_omniauth(auth)
|
70
|
+
if auth[:provider] && auth[:uid] # 인증정보가 있으면..
|
71
|
+
oauth = OauthAuthentication.find_by_provider_and_uid(auth[:provider], auth[:uid])
|
72
|
+
if oauth # 이미 가입되어 있다면 oauth 정보를 갱신함
|
73
|
+
oauth.update_with_credential(auth[:credentials])
|
74
|
+
oauth.save
|
75
|
+
|
76
|
+
return oauth.user
|
77
|
+
else # 가입 정보가 없음!
|
78
|
+
if auth[:info][:email].present? # 이메일이 있으면 가입 또는 연동
|
79
|
+
user = User.find_or_create_by(email: auth[:info][:email]) do |u|
|
80
|
+
u.name = auth[:info][:name] || auth[:info][:email]
|
81
|
+
u.password = Devise.friendly_token[0,20]
|
82
|
+
u.skip_confirmation!
|
83
|
+
u.save
|
84
|
+
end
|
85
|
+
user.confirm! # 인증 대기 중이면 바로 인증시켜버림
|
86
|
+
|
87
|
+
# oauth 정보 생성
|
88
|
+
user.add_oauth_info(auth)
|
89
|
+
|
90
|
+
return user
|
91
|
+
else # 이메일이 없으면 추가정보를 입력받도록 함
|
92
|
+
user = User.new
|
93
|
+
user.errors.add(:email, "email required")
|
94
|
+
|
95
|
+
return user
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
end
|