remotty-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/Gemfile +18 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +234 -0
  6. data/Rakefile +2 -0
  7. data/app/controllers/remotty/base_application_controller.rb +36 -0
  8. data/app/controllers/remotty/users/base_controller.rb +16 -0
  9. data/app/controllers/remotty/users/confirmations_controller.rb +25 -0
  10. data/app/controllers/remotty/users/omniauth_callbacks_controller.rb +102 -0
  11. data/app/controllers/remotty/users/passwords_controller.rb +47 -0
  12. data/app/controllers/remotty/users/registrations_controller.rb +132 -0
  13. data/app/controllers/remotty/users/sessions_controller.rb +48 -0
  14. data/app/models/remotty/base_user.rb +83 -0
  15. data/app/serializers/remotty/user_serializer.rb +30 -0
  16. data/config/locales/ko.yml +58 -0
  17. data/lib/generators/remotty/rails/install_generator.rb +68 -0
  18. data/lib/generators/remotty/rails/templates/add_column_to_users.rb +42 -0
  19. data/lib/generators/remotty/rails/templates/auth_token.rb +22 -0
  20. data/lib/generators/remotty/rails/templates/create_auth_tokens.rb +28 -0
  21. data/lib/generators/remotty/rails/templates/create_oauth_authentications.rb +28 -0
  22. data/lib/generators/remotty/rails/templates/oauth_authentication.rb +18 -0
  23. data/lib/generators/remotty/rails/templates/paperclip_hash.rb +1 -0
  24. data/lib/generators/remotty/rails/templates/user_serializer.rb +3 -0
  25. data/lib/remotty/rails.rb +8 -0
  26. data/lib/remotty/rails/authentication.rb +6 -0
  27. data/lib/remotty/rails/authentication/json_auth_failure.rb +29 -0
  28. data/lib/remotty/rails/authentication/strategies/token_header_authenticable.rb +71 -0
  29. data/lib/remotty/rails/engine.rb +72 -0
  30. data/lib/remotty/rails/version.rb +5 -0
  31. data/rdoc.sh +3 -0
  32. data/remotty-rails.gemspec +35 -0
  33. metadata +231 -0
@@ -0,0 +1,47 @@
1
+ class Users::PasswordsController < Devise::PasswordsController
2
+ include Remotty::Users::BaseController
3
+
4
+ # POST /resource/password
5
+ # email주소를 이용해서 패스워드 변경 요청 메일을 발송함
6
+ #
7
+ # ==== return
8
+ # * +success+ - no_content
9
+ # * +failure+ - validation error message
10
+ #
11
+ def create
12
+ self.resource = resource_class.send_reset_password_instructions(resource_params)
13
+ yield resource if block_given?
14
+
15
+ if successfully_sent?(resource)
16
+ render nothing: true, status: :no_content
17
+ else
18
+ render_error 'VALIDATION_ERROR', resource.errors.full_messages.first
19
+ end
20
+ end
21
+
22
+ # PUT /resource/password
23
+ # 토큰을 이용한 패스워드 변경
24
+ # 성공시 자동으로 로그인을 시도하고 토큰을 생성함
25
+ #
26
+ # ==== return
27
+ # * +success+ - 로그인 후 user with token json return
28
+ # * +failure+ - unauthorized with error message
29
+ #
30
+ def update
31
+ self.resource = resource_class.reset_password_by_token(resource_params)
32
+ yield resource if block_given?
33
+
34
+ if resource.errors.empty?
35
+ resource.unlock_access! if unlockable?(resource)
36
+ sign_in resource_name, resource, :store => false
37
+
38
+ token = resource.generate_auth_token!(auth_source)
39
+ render json: resource.with_token(token)
40
+ else
41
+ render_error 'UNAUTHORIZED',
42
+ resource.errors.full_messages.first,
43
+ :unauthorized
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,132 @@
1
+ class Remotty::Users::RegistrationsController < Devise::RegistrationsController
2
+ include Remotty::Users::BaseController
3
+
4
+ wrap_parameters :user, include: [:email, :name, :password, :password_confirmation, :current_password]
5
+
6
+ # POST /resource
7
+ # 회원가입
8
+ def create
9
+ build_resource(sign_up_params)
10
+ resource.use_password = true
11
+
12
+ # oauth정보가 있으면 validation 체크
13
+ if params[:oauth]
14
+ unless valid_credential?(oauth_params)
15
+ render_error 'UNAUTHORIZED', 'Oauth credentials information is invalid', :unauthorized and return
16
+ end
17
+ end
18
+
19
+ if resource.save
20
+ yield resource if block_given?
21
+
22
+ resource.add_oauth_info(oauth_params) if params[:oauth]
23
+
24
+ if resource.active_for_authentication?
25
+ sign_up(resource_name, resource)
26
+
27
+ token = resource.generate_auth_token!(auth_source)
28
+
29
+ render json: resource.with_token(token)
30
+ else
31
+ expire_data_after_sign_in!
32
+
33
+ render_error 'UNAUTHORIZED',
34
+ find_message("signed_up_but_#{resource.inactive_message}"),
35
+ :unauthorized
36
+ end
37
+ else
38
+ clean_up_passwords resource
39
+
40
+ render_error 'VALIDATION_ERROR',
41
+ resource.errors.full_messages.first
42
+ end
43
+ end
44
+
45
+ # PUT /resource
46
+ # 회원정보 수정 (password 제외한 일반 정보)
47
+ def update
48
+ self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
49
+ prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
50
+
51
+ if account_update_params[:password].blank? # password 수정이 아니면
52
+ account_update_params.delete("password")
53
+ account_update_params.delete("password_confirmation")
54
+
55
+ if resource.update_without_password(account_update_params)
56
+ yield resource if block_given?
57
+
58
+ message_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
59
+ :update_needs_confirmation : :updated
60
+
61
+ sign_in resource_name, resource, :bypass => true, :store => false
62
+
63
+ if message_key == :updated
64
+ render json: resource
65
+ else
66
+ render_error 'UNAUTHORIZED',
67
+ find_message(message_key),
68
+ :unauthorized
69
+ end
70
+ else
71
+ clean_up_passwords resource
72
+
73
+ render_error 'VALIDATION_ERROR',
74
+ resource.errors.full_messages.first
75
+ end
76
+ else # password 수정이면
77
+ if resource.use_password
78
+ resource.update_with_password(account_update_params)
79
+ else
80
+ resource.use_password = true
81
+ resource.update_attributes(account_update_params)
82
+ clean_up_passwords resource
83
+ end
84
+
85
+ if resource.errors.blank?
86
+ render json: resource
87
+ else
88
+ render_error 'VALIDATION_ERROR',
89
+ resource.errors.full_messages.first
90
+ end
91
+ end
92
+ end
93
+
94
+ # DELETE /resource
95
+ # 회원탈퇴
96
+ def destroy
97
+ resource.destroy
98
+ Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
99
+ set_flash_message :notice, :destroyed if is_flashing_format?
100
+ yield resource if block_given?
101
+ render nothing: true, status: :no_content
102
+ end
103
+
104
+ private
105
+
106
+ def oauth_params
107
+ params.require(:oauth).permit :provider, :uid, info: [:name, :image], credentials: [:token, :secret, :expires_at]
108
+ end
109
+
110
+ # credential 체크
111
+ def valid_credential?(oauth_params)
112
+ if oauth_params['provider'] == 'twitter'
113
+ client = Twitter::REST::Client.new do |config|
114
+ config.consumer_key = Settings.omniauth.twitter.consumer_key
115
+ config.consumer_secret = Settings.omniauth.twitter.consumer_secret
116
+ config.access_token = oauth_params['credentials']['token']
117
+ config.access_token_secret = oauth_params['credentials']['secret']
118
+ end
119
+
120
+ begin
121
+ twitter_user = client.user
122
+ if twitter_user.id == oauth_params['uid'].to_i
123
+ return true
124
+ end
125
+ rescue Twitter::Error
126
+ return false
127
+ end
128
+ end
129
+
130
+ false
131
+ end
132
+ end
@@ -0,0 +1,48 @@
1
+ class Remotty::Users::SessionsController < Devise::SessionsController
2
+ include Remotty::Users::BaseController
3
+ include ActionController::Flash
4
+ wrap_parameters :user, include: [:email, :password]
5
+
6
+ # POST /resource/sign_in
7
+ # email과 password로 로그인
8
+ # 새로운 토큰 생성
9
+ #
10
+ # ==== return
11
+ # * +success+ - 로그인 후 user with token json return
12
+ # * +failure+ - unauthorized with error message
13
+ #
14
+ def create
15
+ self.resource = warden.authenticate!(:scope => resource_name)
16
+ sign_in(resource_name, resource, store: false)
17
+ yield resource if block_given?
18
+ token = resource.generate_auth_token!(auth_source)
19
+ render json: resource.with_token(token)
20
+ end
21
+
22
+ # DELETE /resource/sign_out
23
+ # 로그아웃. 로그인이 되어 있지 않아도 에러를 발생하지는 않음
24
+ # 토큰이용시 토큰을 삭제함
25
+ #
26
+ # ==== return
27
+ # * +success+ - no_content
28
+ # * +failure+ - no_content
29
+ #
30
+ def destroy
31
+ user = current_user
32
+
33
+ signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
34
+ if signed_out
35
+ if user && request.headers["X-Auth-Token"].present?
36
+ auth_token = user.auth_tokens.where(token: Digest::SHA512.hexdigest(request.headers["X-Auth-Token"])).first
37
+ auth_token.destroy if auth_token
38
+ end
39
+
40
+ session.options[:skip] = true
41
+ response.headers['Set-Cookie'] = 'rack.session=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT'
42
+ end
43
+ yield resource if block_given?
44
+
45
+ render nothing: true, status: :no_content
46
+ end
47
+
48
+ end
@@ -0,0 +1,83 @@
1
+ module Remotty::BaseUser
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ has_many :auth_tokens, dependent: :destroy
6
+ has_many :oauth_authentications, dependent: :destroy
7
+
8
+ validates :name, presence: true
9
+
10
+ has_attached_file :avatar, :styles => { :original => "512x512#", :small => "200x200#", :thumb => "64x64#" }
11
+ validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
12
+ end
13
+
14
+ attr_accessor :auth_token
15
+
16
+ def generate_auth_token!(auth_source)
17
+ token = nil
18
+
19
+ loop do
20
+ token = Devise.friendly_token
21
+ break token unless self.auth_tokens.where(token: Digest::SHA512.hexdigest(token)).first
22
+ end
23
+
24
+ auth_token = AuthToken.create({user_id:self.id, token: Digest::SHA512.hexdigest(token)})
25
+ auth_token.update_source(auth_source[:source], auth_source[:info])
26
+
27
+ token
28
+ end
29
+
30
+ def with_token(token)
31
+ self.auth_token = token;
32
+ ::UserSerializer.new(self)
33
+ end
34
+
35
+ # oauth authentication 추가
36
+ #
37
+ # * +auth+ : auth 정보
38
+ # * provider, uid, info(name, image), credentials(token, secret, expires_at)
39
+ #
40
+ def add_oauth_info(auth)
41
+ oauth = OauthAuthentication.find_or_create_by(provider: auth[:provider], uid: auth[:uid])
42
+ if oauth
43
+ oauth.update_with_credential(auth[:credentials])
44
+ oauth.user = self
45
+ oauth.save
46
+ end
47
+
48
+ if auth[:info][:image]
49
+ self.avatar_remote_url = auth[:info][:image]
50
+ self.save
51
+ end
52
+ end
53
+
54
+ # remote url attachment helper
55
+ #
56
+ def avatar_remote_url=(url)
57
+ avatar_url = process_uri(url)
58
+ self.avatar = URI.parse(avatar_url)
59
+ # Assuming url_value is http://example.com/photos/face.png
60
+ # avatar_file_name == "face.png"
61
+ # avatar_content_type == "image/png"
62
+ @avatar_remote_url = avatar_url
63
+ end
64
+
65
+ private
66
+
67
+ # fix uri redirection (http -> https)
68
+ def process_uri(uri)
69
+ ret = uri
70
+
71
+ require 'open-uri'
72
+ require 'open_uri_redirections'
73
+ begin
74
+ open(uri, :allow_redirections => :safe) do |r|
75
+ ret = r.base_uri.to_s
76
+ end
77
+ end
78
+
79
+ ret
80
+ end
81
+ end
82
+
83
+
@@ -0,0 +1,30 @@
1
+ # user serializer
2
+ #
3
+ # ==== column
4
+ # * +id+
5
+ # * +name+
6
+ # * +email+
7
+ # * +use_password+
8
+ # * +avatar+
9
+ # * +original+
10
+ # * +small+
11
+ # * +thumb+
12
+ # * +auth_token+
13
+ #
14
+ class Remotty::UserSerializer < ActiveModel::Serializer
15
+ attributes :id, :name, :email, :use_password, :avatar, :auth_token
16
+
17
+ def avatar
18
+ {
19
+ original:object.avatar.url,
20
+ small:object.avatar.url(:small),
21
+ thumb:object.avatar.url(:thumb)
22
+ }
23
+ end
24
+
25
+ def include_auth_token?
26
+ object.auth_token
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,58 @@
1
+ # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2
+
3
+ ko:
4
+ errors:
5
+ messages:
6
+ expired: "가(이) 만료되었습니다. 새로 요청해 주십시오"
7
+ not_found: "를(을) 찾을 수 없습니다"
8
+ already_confirmed: "이미 확인되었습니다, 다시 로그인 해 주십시오"
9
+ not_locked: "가(이) 잠기지 않았습니다"
10
+ not_saved:
11
+ one: "1개의 에러가 발생해서 %{resource}를(을) 저장할 수 없습니다:"
12
+ other: "%{count}개의 에러가 발생해서 %{resource}를(을) 저장할 수 없습니다:"
13
+
14
+ devise:
15
+ failure:
16
+ already_authenticated: '이미 로그인하셨습니다.'
17
+ unauthenticated: '이용하시려면 로그인하거나 가입하셔야 합니다.'
18
+ unconfirmed: '계정 확인 하셔야 이용하실 수 있습니다.'
19
+ locked: '계정이 잠겼습니다.'
20
+ invalid: '이메일이나 패스워드가 다릅니다.'
21
+ invalid_token: '잘못된 인증 토큰 입니다.'
22
+ timeout: '세션이 만료되어습니다, 계속하시려면 로그인해주세요.'
23
+ inactive: '계정이 아직 활성화 되지 않았습니다. '
24
+ not_found_in_database: '이메일이나 패스워드가 다릅니다.'
25
+ sessions:
26
+ signed_in: '성공적으로 로그인 하셨습니다.'
27
+ signed_out: '성공적으로 로그아웃 하셨습니다.'
28
+ passwords:
29
+ send_instructions: '어떻게 비밀번호를 재설정하는지 안내하는 메일을 발송하였습니다. 잠시후 확인해 보세요.'
30
+ updated: '비밀번호를 성공적으로 변경했습니다. 이제 로그인된 상태입니다.'
31
+ updated_not_active: '비밀번호를 성공적으로 변경했습니다.'
32
+ send_paranoid_instructions: "데이터베이스에 고객님의 이메일 주소가 존재하면, 비밀번호 복구 링크가 담긴 이메일을 곧 받으실 수 있습니다."
33
+ confirmations:
34
+ send_instructions: '이메일 주소를 확인하는 메일을 발송하였습니다. 잠시후에 메일을 확인해보세요.'
35
+ send_paranoid_instructions: '데이터베이스에 고객님의 이메일 주소가 존재하면, 이메일 주소를 확인하는 방법이 담긴 이메일을 곧 받으실 수 있습니다.'
36
+ confirmed: '성공적으로 이메일 주소를 확인하였습니다. 이제 로그인된 상태입니다.'
37
+ registrations:
38
+ signed_up: '환영합니다! 성공적으로 가입하셨습니다.'
39
+ signed_up_but_unconfirmed: '이메일 주소 확인 링크가 담긴 메일을 발송하였습니다. 계정을 활성화 하기 위해서 그 링크를 방문해주세요.'
40
+ signed_up_but_inactive: '고객님은 성공적으로 가입하셨습니다. 그러나 아직 계정이 활성화되지 않아 지금 로그인하실 수 없습니다.'
41
+ signed_up_but_locked: '고객님은 성공적으로 가입하셨습니다. 그러나 계정이 잠겨 있어 지금 로그인하실 수 없습니다.'
42
+ updated: '성공적으로 계정이 수정되었습니다.'
43
+ update_needs_confirmation: "성공적으로 계정이 수정되었습니다, 하지만 저희가 이메일주소를 확인해야 합니다. 이메일을 확인하시고 새로 바뀐 이메일 주소를 확인하는 링크를 방문해주세요."
44
+ destroyed: '안녕히가세요! 계정이 성공적으로 삭제되었습니다. 다시 뵙기를 고대합니다.'
45
+ unlocks:
46
+ send_instructions: '계정 잠금을 푸는 링크가 담긴 메일을 발송하있습니다. 잠시후에 확인해 보세요.'
47
+ unlocked: '성공적으로 계정 잠금을 풀었습니다. 계속 이용하시려면 로그인하세요.'
48
+ send_paranoid_instructions: '고객님의 계정이 존재하면, 곧 계정 잠금을 푸는 방법이 담긴 이메일을 받으실 수 있습니다.'
49
+ omniauth_callbacks:
50
+ success: '%{kind} 계정으로 성공적으로 인증되었습니다.'
51
+ failure: '다음과 같은 이유로 %{kind}에서 인증에 실패하였습니다. "%{reason}"'
52
+ mailer:
53
+ confirmation_instructions:
54
+ subject: '이메일 주소 확인 메일'
55
+ reset_password_instructions:
56
+ subject: '비밀번호 변경 확인 메일'
57
+ unlock_instructions:
58
+ subject: '계정 Unlock 메일'
@@ -0,0 +1,68 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Remotty::Rails
5
+ module Generators
6
+ # 마이그레이션 생성 및 각종 클래스&설정 추가 및 변경
7
+ #
8
+ # ==== migration
9
+ # * +add_column_to_users.rb+ - user
10
+ # * +create_auth_tokens.rb+ - auth token
11
+ # * +create_oauth_authentications.rb+ - oauth authentication
12
+ #
13
+ # ==== model
14
+ # * +auth_token.rb+ - auth token
15
+ # * +oauth_authentication.rb+ - oauth_authentication
16
+ # * +user.rb+ - user model에 base include
17
+ #
18
+ # ==== configuration
19
+ # * +paperclip_hash.rb+ - paperclip hash
20
+ #
21
+ # ==== serializer
22
+ # * +user_serializer.rb+ - user model serializer
23
+ #
24
+ # ==== controller
25
+ # * +application_controller.rb+ - application controller에 base include
26
+ #
27
+ class InstallGenerator < ::Rails::Generators::Base
28
+ include ::Rails::Generators::Migration
29
+
30
+ desc "Creates a Remotty Rails model initializer and copy files to your application."
31
+
32
+ source_root File.expand_path("../templates", __FILE__)
33
+
34
+ # migration number 생성용 변수
35
+ @migration_index = 0
36
+
37
+ # migration number는 현재날짜시간 + index(1,2,...) 형식으로 생성함
38
+ def self.next_migration_number(path)
39
+ @migration_index += 1
40
+ (Time.now.utc.strftime("%Y%m%d%H%M%S").to_i + @migration_index).to_s
41
+ end
42
+
43
+ # add & update files
44
+ def copy_purple_attachment
45
+ template 'auth_token.rb', 'app/models/auth_token.rb'
46
+ template 'oauth_authentication.rb', 'app/models/oauth_authentication.rb'
47
+ template 'user_serializer.rb', 'app/serializers/user_serializer.rb'
48
+ template 'paperclip_hash.rb', 'config/initializers/paperclip_hash.rb'
49
+ append_to_file 'config/initializers/paperclip_hash.rb' do
50
+ secret = SecureRandom.hex(40)
51
+ "Paperclip::Attachment.default_options.update({ :hash_secret => '#{secret}' })"
52
+ end
53
+ inject_into_class 'app/controllers/application_controller.rb', ApplicationController do
54
+ " include Remotty::BaseApplicationController\n"
55
+ end
56
+ inject_into_class 'app/models/user.rb', User do
57
+ " include Remotty::BaseUser\n"
58
+ end
59
+ gsub_file 'app/models/user.rb', 'registerable', 'registerable, :confirmable, :omniauthable'
60
+
61
+ migration_template 'add_column_to_users.rb', 'db/migrate/add_column_to_users.rb'
62
+ migration_template 'create_auth_tokens.rb', 'db/migrate/create_auth_tokens.rb'
63
+ migration_template 'create_oauth_authentications.rb', 'db/migrate/create_oauth_authentications.rb'
64
+ end
65
+
66
+ end
67
+ end
68
+ end