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.
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