diff --git a/Gemfile b/Gemfile index 4b76b46..84f46cd 100644 --- a/Gemfile +++ b/Gemfile @@ -56,6 +56,9 @@ gem 'rabl-rails' gem 'omniauth-facebook' gem 'omniauth-google-oauth2' gem 'omniauth-twitter' +gem 'dynamic_form' + +gem 'quiet_assets', group: :development group :production do gem 'rails_12factor' diff --git a/Gemfile.lock b/Gemfile.lock index fb3a8c1..4e01d24 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,6 +54,7 @@ GEM railties (>= 3.2.6, < 5) thread_safe (~> 0.1) warden (~> 1.2.3) + dynamic_form (1.1.4) erubis (2.7.0) execjs (2.2.1) faraday (0.9.0) @@ -116,6 +117,8 @@ GEM orm_adapter (0.5.0) pg (0.17.1) polyglot (0.3.5) + quiet_assets (1.0.3) + railties (>= 3.1, < 5.0) rabl-rails (0.3.4) activesupport (>= 3.1) railties (>= 3.1) @@ -198,6 +201,7 @@ DEPENDENCIES cloudinary coffee-rails (~> 4.0.0) devise + dynamic_form gon jbuilder (~> 2.0) jquery-rails @@ -207,6 +211,7 @@ DEPENDENCIES omniauth-google-oauth2 omniauth-twitter pg + quiet_assets rabl-rails rails (= 4.1.4) rails_12factor diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index db7281b..0bfb80a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,11 +5,7 @@ class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? before_action :authenticate_user! - # migration for new field nickname which is required field. - before_action :is_nickname_not_empty? - - protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) << :nickname @@ -22,5 +18,5 @@ def is_nickname_not_empty? redirect_to edit_user_registration_path end end - + end diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index 420938e..eccf2c8 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -1,71 +1,58 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController - # def facebook - # # You need to implement the method below in your model (e.g. app/models/user.rb) - # @user = User.from_omniauth(request.env["omniauth.auth"]) + def authenticate(provider) + @user = User.new( + provider: provider, + uid: request.env["omniauth.auth"].uid) - # if @user.persisted? and @user.uid != nil - # sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated - # set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format? - # elsif @user.persisted? and @user.uid == nil - + result = User.find_for_oauth(provider, request.env["omniauth.auth"]) - # session["devise.facebook_data"] = request.env["omniauth.auth"] - # redirect_to users_merge_path(@user.id, 'facebook_data') - # else - # session["devise.facebook_data"] = request.env["omniauth.auth"] - # redirect_to new_user_registration_url - # end - # end + case provider + when :twitter + @user.nickname = request.env["omniauth.auth"]["extra"]["raw_info"].screen_name - def facebook - # You need to implement the method below in your model (e.g. app/models/user.rb) - @user = User.find_for_google_oauth2(request.env["omniauth.auth"], current_user) + case result[:status] + when :success + @user = result[:data] + sign_in_and_redirect @user, :event => :authentication + + when :first_login + render sign_up_from_twitter_users_path + end - # OAuth 성공 - if @user.persisted? and @user.uid != nil - flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook" - sign_in_and_redirect @user, :event => :authentication - # 중복 이메일이 있을 경우 - elsif @user.persisted? and @user.uid == nil - session["devise.facebook_data"] = request.env["omniauth.auth"] - redirect_to users_merge_path(@user.id, 'facebook_data') else - session["devise.facebook_data"] = request.env["omniauth.auth"] - redirect_to new_user_registration_url - end - end + @user.email = request.env["omniauth.auth"]["info"].email - def google_oauth2 - # You need to implement the method below in your model (e.g. app/models/user.rb) - @user = User.find_for_google_oauth2(request.env["omniauth.auth"], current_user) + case result[:status] + when :success + @user = result[:data] + sign_in_and_redirect @user, :event => :authentication - # OAuth 성공 - if @user.persisted? and @user.uid != nil - flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google" - sign_in_and_redirect @user, :event => :authentication - # 중복 이메일이 있을 경우 - elsif @user.persisted? and @user.uid == nil - session["devise.google_data"] = request.env["omniauth.auth"] - redirect_to users_merge_path(@user.id, 'google_data') - else - session["devise.google_data"] = request.env["omniauth.auth"] - redirect_to new_user_registration_url + when :first_login + render nickname_new_users_path + + when :duplicated + @user = User.find_by_email(@user.email) + @user.provider = provider + @user.uid = request.env["omniauth.auth"].uid + + render merge_users_path + + when :duplicated_by_oauth + flash[:notice] = result[:data] + " 서비스로 이미 회원가입 되어있습니다. 해당 서비스로 로그인해주세요" + redirect_to new_user_session_path + end end end - + def twitter - @user = User.find_for_twitter_oauth(request.env["omniauth.auth"], current_user) + authenticate(:twitter) + end - if @user.persisted? and @user.uid != nil - sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated - set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format? - elsif @user.persisted? and @user.uid == nil - session["devise.twitter_data"] = request.env["omniauth.auth"] - redirect_to users_merge_path(@user.id, 'twitter_data') - else - session["devise.twitter_data"] = request.env["omniauth.auth"] - redirect_to new_user_registration_url - end + def facebook + authenticate(:facebook) + end + + def google_oauth2 + authenticate(:google_oauth2) end - -end \ No newline at end of file +end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index a937a59..11ceb4a 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,3 +1,28 @@ class Users::RegistrationsController < Devise::RegistrationsController skip_before_action :is_nickname_not_empty? -end \ No newline at end of file + + def update + if current_user.provider == nil + super + else + account_update_params = devise_parameter_sanitizer.sanitize(:account_update) + + # required for settings form to submit when password is left blank + if account_update_params[:password].blank? + account_update_params.delete("password") + account_update_params.delete("password_confirmation") + account_update_params.delete("current_password") + end + + @user = User.find(current_user.id) + if @user.update_attributes(account_update_params) + set_flash_message :notice, :updated + # Sign in the user bypassing validation in case their password changed + sign_in @user, :bypass => true + redirect_to after_update_path_for(@user) + else + render "edit" + end + end + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 87f2669..2691836 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -5,17 +5,50 @@ def show end def merge + end + + def merge_callback + + @user = User.find_by_email(params[:user][:email]) + @user.provider = params[:user][:provider] + @user.uid = params[:user][:uid] + if @user.valid_password?(params[:user][:password]) + if @user.save + sign_in_and_redirect @user, :event => :authentication + else + render merge_users_path + end + else + flash[:notice] = "Password is not valid!" + render merge_users_path + end + end + + def nickname_new + end - @user = User.find(params[:id]) - @provider = params[:provider] + def nickname_new_callback + @user = User.new(params[:user].permit!) - if params[:callback] == 'callback' - provider_session = session["devise." + @provider] + if @user.save + sign_in_and_redirect @user, :event => :authentication + else + render nickname_new_users_path + end - @user.merge(params[:id], provider_session["provider"], provider_session["uid"]) - redirect_to root_path - end + end + + def sign_up_from_twitter + end + + def sign_up_from_twitter_callback + @user = User.new(params[:user].permit!) + if @user.save + sign_in_and_redirect @user, :event => :authentication + else + render sign_up_from_twitter_users_path + end end end diff --git a/app/models/user.rb b/app/models/user.rb index ebcdd1d..129cea4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,12 +1,10 @@ class User < ActiveRecord::Base - # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable has_many :histories has_many :todos has_many :history_users, foreign_key: :assignee_id - has_many :assigned_histories, through: :history_users - + has_many :assigned_histories, through: :history_users + has_many :project_users, foreign_key: :assignee_id has_many :assigned_projects, through: :project_users @@ -25,68 +23,45 @@ def to_param end def self.find_by_nickname(nickname) - #where(arel_table[:nickname].matches("#{nickname}")).take(1) - user = User.where(:nickname => nickname).first - end - - def self.from_omniauth(auth) - @my_logger ||= Logger.new("#{Rails.root}/log/my.log") - where(auth.slice(:provider, :uid)).first_or_create do |user| - @my_logger.debug "test facebok" - user.email = auth.info.email - user.password = Devise.friendly_token[0,20] - # user.password = nil - user.nickname = auth.info.name - - @my_logger.debug user.inspect - end + user = User.where(nickname: nickname).first end - def self.new_with_session(params, session) - super.tap do |user| - if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] - user.email = data["email"] if user.email.blank? + def self.find_for_oauth(provider, access_token) + case provider + when "twitter" + if user = User.where(uid: access_token.uid, provider: access_token.provider).first + return {data: user, status: :success} + else + return {data: nil, status: :first_login} end - end - end - def self.find_for_google_oauth2(access_token, signed_in_resource=nil) - data = access_token.info - - user = User.where(:email => data["email"]).first + else + email = access_token.info[:email] + + if user = User.where(uid: access_token.uid, provider: access_token.provider).first + return {data: user, status: :success} + elsif user = User.find_by_email(email) + if user.provider.nil? + return {data: nil, status: :duplicated} + else + return {data: user.provider, status: :duplicated_by_oauth} + end + else + return {data: nil, status: :first_login} + end - # Uncomment the section below if you want users to be created if they don't exist - unless user - user = User.create(provider:access_token.provider, - uid:access_token.uid, - email: data["email"], - password: Devise.friendly_token[0,20], - nickname: data["name"]) end - user end - - def self.find_for_twitter_oauth(auth, signed_in_resource=nil) - user = User.where(:email => auth.extra.raw_info.screen_name + "@todo.nut").first - - unless user - user = User.create(provider:auth.provider, - uid:auth.uid, - email: auth.extra.raw_info.screen_name + "@todo.nut", - nickname: auth.extra.raw_info.screen_name, - password:Devise.friendly_token[0,20]) - end - - user + def update_from_twitter(id, email) + user = User.find(id) + user.email = email + user.save! end - def merge(id, provider, uid) - user = User.where(:id => id).first - user.provider = provider - user.uid = uid - user.save + def password_required? + if provider.nil? + super + end end - - end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 637de6d..cbd7565 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -4,43 +4,49 @@

Edit <%= resource_name.to_s.humanize %>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= devise_error_messages! %> - -
- <%= f.label :email %> - <%= f.email_field :email, autofocus: true, class: "form-control" %> -
- - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
- <% end %> - -
- <%= f.label :nickname %> - <%= f.text_field :nickname, class: "form-control" %> -
- -
- <%= f.label :password %> (leave blank if you don't want to change it) - <%= f.password_field :password, autocomplete: "off", class: "form-control" %> -
- -
- <%= f.label :password_confirmation %> - <%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %> -
- -
- <%= f.label :current_password %> (we need your current password to confirm your changes) - <%= f.password_field :current_password, autocomplete: "off", class: "form-control" %> -
- -
- <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-default" %> - <%= link_to "Back", :back, class: "btn btn-default" %> - <%= f.submit "Update", class: "btn btn-default" %> -
+ <%= devise_error_messages! %> + + + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %> + +
+ <%= f.label :nickname %> + <%= f.text_field :nickname, class: "form-control" %> +
+ + <% if current_user.provider == nil %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, class: "form-control" %> +
+ +
+ <%= f.label :password %> (leave blank if you don't want to change it) + <%= f.password_field :password, autocomplete: "off", class: "form-control" %> +
+ +
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %> +
+ + +
수정하기 위해선 비밀번호를 입력해야 합니다 + <%= f.label :current_password %> + <%= f.password_field :current_password, autocomplete: "off", class: "form-control" %> +
+ <% end %> + +
+ <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-default" %> + <%= link_to "Back", :back, class: "btn btn-default" %> + <%= f.submit "Update", class: "btn btn-default" %> +
+ <% end %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index afc9e02..629b17a 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -3,7 +3,12 @@

Sign in

+ + <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> + + +
<%= f.label :email %> <%= f.email_field :email, autofocus: true, class: "form-control" %> @@ -34,5 +39,9 @@
<%= render "devise/shared/links" %>
+ + <% if flash[:notice] %> +

<%= flash[:notice] %>

+ <% end %>
diff --git a/app/views/users/merge.html.erb b/app/views/users/merge.html.erb index 4a446ae..a645d7c 100644 --- a/app/views/users/merge.html.erb +++ b/app/views/users/merge.html.erb @@ -1,7 +1,26 @@

중복되는 이메일이 있어요 => <%= @user.email %>

+

이 아이디와 통합하려면 기존 계정의 패스워드를 입력하세요

-

이 아이디와 통합할까요?

+
+<%= form_for @user, url: merge_callback_users_path, method: "post" do |f| %> + + <%= f.error_messages %> -<%= link_to 'Yeah', users_merge_path(@user.id, :provider => @provider, :callback => 'callback'), class: "btn btn-primary" %> -<%= link_to 'NoNo', root_path, class: "btn btn-default" %> \ No newline at end of file + <% if flash[:notice] %> +

<%= flash[:notice] %>

+ <% end %> + +
+ <%= f.label :password %> + <%= f.password_field :password, autofocus: true, class: "form-control" %> +
+ + <%= f.hidden_field :provider, value: @user.provider %> + <%= f.hidden_field :uid, value: @user.uid %> + <%= f.hidden_field :email, value: @user.email %> + + <%= f.submit "Submit", class: "btn btn-primary" %> + +<% end %> +
\ No newline at end of file diff --git a/app/views/users/nickname_new.html.erb b/app/views/users/nickname_new.html.erb new file mode 100644 index 0000000..ed3d31f --- /dev/null +++ b/app/views/users/nickname_new.html.erb @@ -0,0 +1,24 @@ +
+<%= form_for @user, url: nickname_new_callback_users_path, method: "post" do |f| %> + +

처음이십니다. 새로운 닉네임을 입력하세요

+ + <%= f.error_messages %> + + <% if flash[:notice] %> +

<%= flash[:notice] %>

+ <% end %> + +
+ <%= f.label :nickname %> + <%= f.text_field :nickname, autofocus: true, class: "form-control" %> +
+ + <%= f.hidden_field :provider, value: @user.provider %> + <%= f.hidden_field :uid, value: @user.uid %> + <%= f.hidden_field :email, value: @user.email %> + + <%= f.submit "Submit", class: "btn btn-primary" %> + +<% end %> +
\ No newline at end of file diff --git a/app/views/users/sign_up_from_twitter.html.erb b/app/views/users/sign_up_from_twitter.html.erb new file mode 100644 index 0000000..0cfeef8 --- /dev/null +++ b/app/views/users/sign_up_from_twitter.html.erb @@ -0,0 +1,35 @@ +

새 이메일을 입력하세요 - Twitter

+ +
+ <%= form_for @user, url: sign_up_from_twitter_callback_users_path, method: "post" do |f| %> + + + <%= f.error_messages %> + + + <% if flash[:notice] %> +

<%= flash[:notice] %>

+ <% end %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, class: "form-control" %> +
+ + <% if f.error_message_on(:nickname).blank? %> + <%= f.hidden_field :nickname, value: @user.nickname %> + <% else %> +
+ <%= f.label :nickname %> + <%= f.text_field :nickname, autofocus: true, class: "form-control" %> +
+ <% end %> + + + <%= f.hidden_field :provider, value: @user.provider %> + <%= f.hidden_field :uid, value: @user.uid %> + + <%= f.submit :class => 'btn btn-success'%> + + <% end %> +
diff --git a/config/routes.rb b/config/routes.rb index 058501f..c43593a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,17 +1,24 @@ Rails.application.routes.draw do - # get 'users/merge(/:email)' - - get '/users/merge/:id/:provider(/:callback)', to: 'users#merge', as: 'users_merge' - - devise_for :users, :controllers => { + devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :registrations => "users/registrations", :sessions => "users/sessions" } - #get '/users/(/:nickname)/edit', to: 'users/registrations#edit', as: 'edit_user' + resources :users, only: :index do + collection do + get 'sign_up_from_twitter' + post 'sign_up_from_twitter_callback' + + get 'merge' + post 'merge_callback' + + get 'nickname_new' + post 'nickname_new_callback' + end + end + get '/users/(/:nickname)', to: 'users#show', as: 'show_user' - #resources :users, only: [:show] resources :projects do resources :todos do @@ -35,6 +42,6 @@ end - + root 'projects#index' end diff --git a/db/schema.rb b/db/schema.rb index ed36880..283cb55 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -50,6 +50,10 @@ t.integer "history_id" t.datetime "created_at" t.datetime "updated_at" + t.string "image_file_name" + t.string "image_content_type" + t.integer "image_file_size" + t.datetime "image_updated_at" t.string "image" end @@ -109,7 +113,7 @@ create_table "users", force: true do |t| t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false + t.string "encrypted_password", default: "" t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at"