From 08439e7f5814c043957d24f05560d62e671878d3 Mon Sep 17 00:00:00 2001 From: mlorb Date: Mon, 26 Feb 2018 11:05:05 +0100 Subject: [PATCH] sign up with linkedIn account --- Gemfile | 1 + .../linkedin/Sign-in-Small---Active.png | Bin 0 -> 2469 bytes .../linkedin/Sign-in-Small---Default.png | Bin 0 -> 2468 bytes .../images/linkedin/Sign-in-Small---Hover.png | Bin 0 -> 2475 bytes .../users/omniauth_callbacks_controller.rb | 66 ++++++++++++++++++ .../users/registrations_controller.rb | 55 +++++++++++++-- app/models/user.rb | 8 +++ .../registrations/new_with_provider.html.erb | 37 ++++++++++ app/views/users/shared/_links.html.erb | 15 +++- config/environments/development.rb | 3 + config/environments/production.rb | 3 + config/initializers/devise.rb | 2 + config/initializers/extends.rb | 5 +- config/initializers/paperclip.rb | 2 + config/locales/en.yml | 8 +++ config/routes.rb | 2 + lib/tasks/data.rake | 6 ++ 17 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 app/assets/images/linkedin/Sign-in-Small---Active.png create mode 100644 app/assets/images/linkedin/Sign-in-Small---Default.png create mode 100644 app/assets/images/linkedin/Sign-in-Small---Hover.png create mode 100644 app/views/users/registrations/new_with_provider.html.erb diff --git a/Gemfile b/Gemfile index ff658fde3..1bea45cc0 100644 --- a/Gemfile +++ b/Gemfile @@ -17,6 +17,7 @@ gem 'font-awesome-rails', '~> 4.7.0.2' gem 'recaptcha', require: 'recaptcha/rails' gem 'sanitize', '~> 4.4' gem 'omniauth' +gem 'omniauth-linkedin-oauth2' # Gems for API implementation gem 'jwt', '~> 1.5' diff --git a/app/assets/images/linkedin/Sign-in-Small---Active.png b/app/assets/images/linkedin/Sign-in-Small---Active.png new file mode 100644 index 0000000000000000000000000000000000000000..dea692fd904f6a52798d58f55523437638994e33 GIT binary patch literal 2469 zcmaJ@c{o&iA0J%XNH1+fn8v=0F=H8X9+GA(Q^q=#B{I#NVJ5SfImIB`Ra#ysC*FSNar2`5hOM>1oQ@}bYXZiXa|GI z=rSq3kT2N{pmEve)K!dmB%3E;!(es}kvuBxFbE+IfgwzeJ#wbH9*JPm?UDPf$rfZD z0SsljM)5(PD0d1i>M#vYM>_04*hK;o0X7Ix5s~aLjsS?XM}E}>B==P}8j1J{fezav z|4z!6?1><7`5?mD+!{r*z+w-3b;r3G|Au?x~rjh0D%uuAugZ7<%X?w(KD0_aRs4V9)dtX z7?G(oCTG<){z@Q|0TM?5Q8_e_M6^drB+QviI^c-I*jQq1Z1H#}3k=4|%Fz;ob+T~A z*jf>=Rzw_bjZ5Uxj<7)vw8o|X!1#l{iH6+9{>^e0ruuP+hHC9r1KBG%C(AWadTn#QTdg z%XLquHH-x9L}dR0QBF6|aNWv&aiu6#+@Bma7?F|MudU_1bbw`AV{A+YgoJW~ZjG9& zFV%PND9#g)t6eQw{Nxhfvq3aIsb8BEioes^5)gIkjY-{|*}`pcae_Dg z7vJi&6pul56Wl;2pr>I}e|n3DMx&lI??JQ{(6h@RvuL5SHe-F-$%^@NS=l~)#N@Pq z#nTHoc$s1DHM$dgZ{7T+F|;uLq1@8k+~`Ti3SsB5m|kiBcEfT#s#W{sbO;L!z!~P} znO>bLX6UfSj*|3(pO^X@voSnVC4vAT?#E zWJ^cXjsy%LQ5cj^hbnuVY;i0`Ph_7x#9u#Gt}>lmqWdsS;ng@iO)vG;xN-LF>p9Vg zXUCq?qPc@{Im>y`Q~8ZPsQ$n`I&Ep9tr2;nvHg1Ocf%HRt`oM~1PKaL#yJD+GkYfe zU*|0P81-&*52^m5uU6W`>PFq_;g_Dd&<1^ATxwtPimfXdQTH2h=D$oyzJBf2ou?es zSPbh?1NP>NT8i(>HX5&^DyQ|Gb;!S!i$DLWWTrH}`Gi!wuX@Qx+g+dbF2zMmdcJkf zzndk$H0XU`658>4rn9+opzN1iq$Hh!pW})mx~D_@Zcfe_ zM};axcOCDlEe{eS?H+YBI=;L1Q=R{N+ZOw%^QVx6l!5)Iq;pc#`~G)|&yOvZk0%by zjQ)kdLr2OB6G%zWc75YiWgF|~#CG2i;U$E)ZLdfFo1WZCNK_(4$TPLg6lb`xW*bxa zfS@jqVQ{}gQz^ug+@|Dal3}Pwf08TS-|}{ zW{Y%{W1+`U?crlrZY*6`P;9UI&`dlB%v0()E2+0W1!hQ8s` z;X9k()6P@&c;pvdAGhS!&o(*_UgZ@l=$Eh4S2+}4n!lrWvRcE(bI=tnaw~fNUN_hC zU~B+sT=lY9dqy9lce23}_99dM4{4d!iO2@zM3Z*MPeYq~U-$T|{5F=6opZp8UF`yQ z6rIfiauw(Osj`;Z7Q4@ih|w-;PRh9E{M||=`=Wzq&nw6)C@Y-lRK0v-mQbI6Z|pHg z48N^Z_Ve<3ahv_l*f)9iYHPyPCfr?3RT5=SBx_h_{fFLycsl%T77}`ifO+52P zx;Zldg~arP6cf|)iCw@a%7epdK*|J88tiS|rp?=#tl9sjsAS(k%KX!KTKexd1ep!% zlb*6_B$q&U3jY+Y3Q!y_(o13Rl}OVh!l7mjDKU#mIC4{%)kv?hdqz7@6h zJ@{N}Oze_A`3m1RqB zcis3Dl!A;H2cYMhw>O5HnQ4MHuZ|tK`(V#Q zTkZ<3f*&iLr4Xd>A)FIoT_0dI7X*iY1j}S^<4cS7)$dj}5~PvIi)At6Hyl(tW;X^Z zuCF$4Y9#A!bt#k|S~9pFp$b1T;C~PNVx?z-@PZdrv_3|6d$<{9hS2#7Ep}Qs`JWt(Ik^){cLgW@2P#@C^8f$< literal 0 HcmV?d00001 diff --git a/app/assets/images/linkedin/Sign-in-Small---Default.png b/app/assets/images/linkedin/Sign-in-Small---Default.png new file mode 100644 index 0000000000000000000000000000000000000000..f8129afe228724278d7a687894cee5b2bd328080 GIT binary patch literal 2468 zcmaJ@dpwhU8y}vON)kDxn!CkHvja=ptgMYp8^c6LX1m9*L)$PFO35Lwl0%OQIpk1@ zC#h7Dybh&urj#T?Y7X^Ah@PqRynnpC_vdrpzu)!yT;K2Y{ax4hk2{*-uuXlT!9oZG zqE5A=I4joEig)<}RmHd9>CGXu-i&yMtkC6cMdy3SL z2>cM`PG>;LLNN%%nqd)a6b22o#F?S77C1C|0~CWonWE^U-XMsAo zG89f{v3Y{oc-?mZosOppBvO`u4N@sYKtW-~<8km93J!xd$8N>pY*1*ljRnaZjj=)5 zqBmKPF%}d{%Q-AX$PVCx0_hx<^ADE%TkNbC_##DR3Ml3Uf*f11kPrQSXFTusS`?%D zot7V1&hNF5ev3sa#2{xU`(KluJ5tzZcKge>ir|;?L4m^VVui0u=5cEv5LI0&g~XI~ zeAwm3aCOz*2Zie%-41sotpbjCdTNleJYnk*#eeyqZ8WYs#KEG8w$l~Nuxs2$)EWzW zZ?DIz=V9@ibGDk$oLZb=Z!?ZtEe~F};L+iRndA?3rIw}RFW<9ZxUR?D=Ox3hrmmEY z-Mm*a)_uF-5^XBM@O{1dLkPNd@t5#>_kO_nYmtpnJsx^zY@9j-GQ<3yBc`akl zVUyI`Ew<~r3@@6t-wx1y$50V^2bX-QfEsHaHXjNYV5CO%MqHd6@Xf9?0z$^!)C=kh zFQ~kIa;SQm!TPMC#4PGH!cX@t?if9^*d{jMZGA$>OWup-@zI@&e28iP{x~pdb+xQ3 zzl1Meqcu@9uSDMRm|W1gG5U|};q^KtPD<&K3#}$}a~oUV6Q$QOQ<{d-txM~)CJ3v8 z+|KF@KJi9e_$*tN@oLEGDy1t|LOXFvdvlx)5&y7H -gbmi0JsIl?al{$UZj;|}7 z;CxrVaZi!ctNTVdsb2@nxap+)rXbzsGxfBL-Vr4euG(AsuDzM~RFYO)}l}8*3 z%ex!>Dh->mZvonw>}{E_$Xmap&`~4jtZ92*W@&=S)W=Z zC6X11J^AvZwf@WGlJ&bwHFWUB+3~LC0h#gkD+teZVog<4Ab&Nul!%nycBJ8Pq z@1zj_98YGq?x;EXt*>fQaz{ly^~xkVv(09zAmR+|6SD)PBU-=sGJu^)UZk|UU^GW+ zKK#)>%<0~yJ9e#`+zNwS9&kK5ZlcoSPE_58nU~|e#0Htlz2PyOvSjO(dplcl{HS`Nb0rQ3WpY=2t&Hb$@8QMerBwYGehjbz#g3s?b z@2J`HawkHHg>RA4(MzoLKY zsT27H);`t1?s9*1Q)#S)anh9p*bZ34XmH;o*-D94yKF_M=|y+agVY++=M}!5m+RF? zg4K>Hgq6nzKMZ!~(H4K|^MfZX6O+P-0gbeEI)@G>%C9aBG;O|+#fa1G-ZC;HyRyJ6 zQ8mmBTZ|}L0qZz_P?9Fuxav*tR-AcS)b)2R+ot_=<2UQTtRGb#@!NJdVq|$^Tx~T+ z6ANv<6J5cTf3?wOXF5B8>z$O>sru+PUeviU`IW(}>CXjf%rina@1Vwebr;FDJ#D)j zx+GC)U|`S)fqEu$_cRQh9t8ZZS~g|g+VJooGGaI*#`n-*UYHy>EjGEC_2n9QNreO7 z#dnjI@7ozM*XngQ_o`h05E-d9pL($gxYTN*r40^7FhJS(27mRqFBWqZBv{yGSgBvU5 z9EIBH|CuMApAeFHJZW%*K;7|ag7I3klbAbyL&MCa9h0{`+9Zz*=F5*7a0`-@0~_3o zinFS?Z0MUU9sI7i(tDrr?H;n3)4kN|uGxs}^4MUP(r3rRH2z5Rt4JLLQVtq*DI}$L|4rlDf2f83cVQ)60jk+I@7T< z@rPZfR8NKPt}3IcC5LE^!einWa`2~~xw`wc-uMQOWoUz|>%7;MyX-4`85$nM9|iQ9 zF^dK&6Gg_F%mrin`RyKEh_jmZ~?sja4JMAX213U$SX^u@;YW7TUG(yGB6IZ7MsQv$fwHBx4O|xPO~}J#=*2Wf=Y2q z&hqPaeEf`?PxV;2YqQb8gZcHri9;Rn5eTSr4E)@S5Ogcg^P4E4V) aL_t)e)~>2Oj9WkZ-$b=>pj_SR8U8n+!X0S< literal 0 HcmV?d00001 diff --git a/app/assets/images/linkedin/Sign-in-Small---Hover.png b/app/assets/images/linkedin/Sign-in-Small---Hover.png new file mode 100644 index 0000000000000000000000000000000000000000..643236eec81478a14fca58654bbcd7d8c206e9e8 GIT binary patch literal 2475 zcmaJ@c|4SB8=iy^b-rvRWen-0n1wNBGL7Xm*=8`-R5Z=J7|hbls~HL%%h7VmHj{%Q zW#7WFBpvjfq*R=;9a~7{NZC4}@b!&OI^Q4ly}#f4KF|I9uIsw*=f1B$-ZL)L{VGaY zN-!8q#oi8}N!MiQtF9m~{g$@XPD+<8kgYf5#`TAUbUp~PVsejyaC2%m z6ih_?U6eP)1#ZLTgK(@d)`)?^py4>YF&b-%N2B+^F(|YN5{*J)@J47f!4yY8o54Rn z2x&Gx)1N>C$e(jbBO)RYf_MZZQYaJ}3r&o<`~V~xkH;fX7$gQ`Bt;kr!Z;9JWW*8Z ztttSZfWc?+AQqPcUs0qV<%U8;gtXGXufXPgk>vbCi9n$c>^TC6&S8M|01+XTFlMos1S=fc%mia*ipSfc&}dszD-$%v z7DYyzo7!MZ0UU0X3vd~sY>)%3a+&{dvESsbc!AB6W(Gh$>o~|H^SNyJr#ll^U#SHH z;4x?uEbvXe&s^qLYWd8y{U#SFEe5$V+5egJ>XFnwE88!=l?Gp&4|1e-=SzKU$e2}z z!Q{8w16J;$zSlk~P9EUqNGtfCGJHj2-(zl;k%*|@WFP2M0+f<8YJZ7o?dyac2Oam6 zP;eP_bs%2wO6iwsNjgFI!DgF_00B7TA||C?J+wtroUx<;WqLJ?*5T^r2PTdsX9g@< zj14SC423n$pJ*717&_-Gmf$WF)SkY#`}Cw5aqzjYEKGgwI zG_#WI)JpDG`9AGrqmr|7FNDiPhvJ4lDkS<;b}rq@jgk*0RL{fhhr>fPN#3Ht{R45b z3$&40rdIHVJh#*`+N&B;!He+JNyN6G?_L>AUNlf)Y+7^U*@5^CT|d|jm=`6KkqH(E z8g*Q*530(%&}sHoyX>^GO)JsH_sMz4+k ze&UyfdR~mq`2_Tg$NE5GR@3Qn%S^A~yBBxN8d#{~Vtq6BwZ71v$%9YE7wc_8oF6!( zyL={)lWEN=_NiZtNtn$RE(>Z6-+PdHBjj^iAC~5{KT&1*Km`Nb{G3B+b@?9g)_az& zztwQ)_q@}-zuhYF9Y*=%{s+j)pgeNCtK@}Ne{@*$ZJ6brpF9jN zloRW(w3brvg2zDt8@rdgxMP>v)_r`mjdW>I{cuBTQI`20@#2_vacWOt)q^yjq8X1y zfG?kz&kIvhnXA>Q%t7w*yIFsz%fjpoPgNB$K0R9q-MX2iS-0F_Q`x~Yv@|Zb*E5xq zRC+BX+n3<%l%9XQqt{Op7k8&v?a%K{{49om__J^}8j!hhZ7MjuGOk4|S{N zV~ACeBS1}c7-M^L?7E6%K%s$@Q4Qw*0ovCz9(QRM=(1 zc8L9$!rOOmr9in|E=!8=z_JPMU6- z@_2m&%fr3|D0*>@8-DDtDu~jLA9XiqAx{&Uk0mR9<+MnDhp-+{w%N_h2bKrwdnaQasDykay-oH;h}5HL}F)$+{n zY>FBz!;4RjSR(@-k>gBt>LVw(`$ACZ_X88VWJQ9u(M$E}CoK}Pvd;#cd{r1Vh)AwX z?)U5cGs(uKkez9gt|&>G-)XX4LAl)d^wv_dvu9DQ4!O;Rp7nGWr`WZL+H`bZ2s5l5 z`SC=PWU%~Qf3(tp(8QrNI+1R`KJL`>x$f?hZI=^0;j-(MRj`5n@dW+3n#vcPM{miF4(~tW5m65EnXIHKKRt#G;|r zhix(1{+Cl^Ye>vT8BNVUHuVu(2DP}XievwYn@47#)A>2&anrToBl^^u5kGAi;M8(U zka_!W&dAgf_UoY&*7`=L%p2-@$!=to6v?_a)hFj4*?_TQMb(SXmDVa6m}xf6U(G65 z;;d_l47v*&Qui{s?^+F4hRfFaPKj-zN4+nJ^qUpr5ZVgQw_gtp>W@+*7oj8!?V;Qy zYFJjqwZ!5Y^uMf3PmH#UiNR_q3Wl{}-**Al3i? literal 0 HcmV?d00001 diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index 27b884710..7b0bff2b9 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -1,6 +1,10 @@ module Users class OmniauthCallbacksController < Devise::OmniauthCallbacksController + include UsersGenerator + skip_before_action :verify_authenticity_token + before_action :sign_up_with_provider_enabled?, + only: :linkedin # You should configure your model like this: # devise :omniauthable, omniauth_providers: [:twitter] @@ -9,6 +13,55 @@ module Users # def twitter # end + def linkedin + auth_hash = request.env['omniauth.auth'] + + @user = User.from_omniauth(auth_hash) + if @user && @user.current_team_id? + # User already exists and has been signed up with LinkedIn; just sign in + set_flash_message(:notice, + :success, + kind: I18n.t('devise.linkedin.provider_name')) + sign_in_and_redirect @user + elsif @user + # User already exists and has started sign up with LinkedIn; + # but doesn't have team (needs to complete sign up - agrees to TOS) + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.complete_sign_up')) + redirect_to users_sign_up_provider_path(user: @user) + elsif User.find_by_email(auth_hash['info']['email']) + # email is already taken, so sign up with Linked in is not allowed + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.email_already_taken', + email: auth_hash['info']['email'])) + redirect_to after_omniauth_failure_path_for(resource_name) + else + # Create new user and identity; and redirect to complete sign up form + @user = User.new( + full_name: auth_hash['info']['name'], + initials: generate_initials(auth_hash['info']['name']), + email: auth_hash['info']['email'], + password: generate_user_password + ) + @user.avatar_remote_url = (auth_hash['info']['image']) + user_identity = UserIdentity.new(user: @user, + provider: auth_hash['provider'], + uid: auth_hash['uid']) + unless @user.save && user_identity.save + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.failed_to_save')) + redirect_to after_omniauth_failure_path_for(resource_name) and return + end + redirect_to users_sign_up_provider_path(user: @user) + end + end + # More info at: # https://github.com/plataformatec/devise#omniauth @@ -28,5 +81,18 @@ module Users # def after_omniauth_failure_path_for(scope) # super(scope) # end + + private + + def sign_up_with_provider_enabled? + render_403 unless Rails.configuration.x.enable_user_registration + render_403 unless Rails.configuration.x.linkedin_signin_enabled + end + + def generate_initials(full_name) + initials = full_name.titleize.scan(/[A-Z]+/).join + initials = initials.strip.empty? ? 'PLCH' : initials[0..3] + initials + end end end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index dbda51b4a..f127dfd13 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,5 +1,9 @@ class Users::RegistrationsController < Devise::RegistrationsController prepend_before_action :check_captcha, only: [:create] + before_action :registration_enabled?, + only: %i(new create new_with_provider create_with_provider) + before_action :sign_up_with_provider_enabled?, + only: %i(new_with_provider create_with_provider) def avatar user = User.find_by_id(params[:id]) || current_user @@ -122,12 +126,9 @@ class Users::RegistrationsController < Devise::RegistrationsController end end - def new - render_403 && return unless Rails.configuration.x.enable_user_registration - end + def new; end def create - render_403 && return unless Rails.configuration.x.enable_user_registration build_resource(sign_up_params) valid_resource = resource.valid? # ugly checking if new team on sign up is enabled :( @@ -174,6 +175,36 @@ class Users::RegistrationsController < Devise::RegistrationsController end end + def new_with_provider; end + + def create_with_provider + @user = User.find_by_id(user_provider_params['user']) + # Create new team for the new user + @team = Team.new(team_provider_params) + @team.validate + + if @team.valid? && Rails.configuration.x.new_team_on_signup + # Set the confirmed_at == created_at IF not using email confirmations + unless Rails.configuration.x.enable_email_confirmations + @user.update!(confirmed_at: @user.created_at) + end + + @team.created_by = @user # set created_by for team + @team.save! + + # Add this user to the team as owner + UserTeam.create(user: @user, team: @team, role: :admin) + + # set current team to new user + @user.current_team_id = @team.id + @user.save! + + sign_in_and_redirect @user + else + render :new_with_provider + end + end + protected # Called upon creating User (before .save). Permits parameters and extracts @@ -191,6 +222,14 @@ class Users::RegistrationsController < Devise::RegistrationsController tmp.merge(:initials => initials) end + def team_provider_params + params.require(:team).permit(:name) + end + + def user_provider_params + params.permit(:user) + end + def account_update_params params.require(:user).permit( :full_name, @@ -268,6 +307,14 @@ class Users::RegistrationsController < Devise::RegistrationsController end end + def registration_enabled? + render_403 unless Rails.configuration.x.enable_user_registration + end + + def sign_up_with_provider_enabled? + render_403 unless Rails.configuration.x.linkedin_signin_enabled + end + # Redirect to login page after signing up def after_sign_up_path_for(resource) new_user_session_path diff --git a/app/models/user.rb b/app/models/user.rb index e9265fbc6..cca3b9409 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -217,6 +217,14 @@ class User < ApplicationRecord self.full_name = name end + def avatar_remote_url=(url_value) + self.avatar = URI.parse(url_value) + # Assuming url_value is http://example.com/photos/face.png + # avatar_file_name == "face.png" + # avatar_content_type == "image/png" + @avatar_remote_url = url_value + end + def current_team Team.find_by_id(self.current_team_id) end diff --git a/app/views/users/registrations/new_with_provider.html.erb b/app/views/users/registrations/new_with_provider.html.erb new file mode 100644 index 000000000..2feddd300 --- /dev/null +++ b/app/views/users/registrations/new_with_provider.html.erb @@ -0,0 +1,37 @@ +<% provide(:head_title, t('users.registrations.new.head_title')) %> + +
+

<%= t 'users.registrations.new_with_provider.head_title' %>

+
+ <%= form_for(:team, as: resource_name, url: users_complete_sign_up_provider_path, html: { id: "sign-up-provider-form" } ) do |f| %> + <%= hidden_field_tag :user, params['user'] %> + + <% if Rails.configuration.x.new_team_on_signup %> +
+ <%= f.label :name, t('users.registrations.new.team_name_label') %> + <%= f.text_field :name, autofocus: true, class: 'form-control' %> + <%= t 'users.registrations.new.team_name_help' %> +
+ <% end %> + +
+ <%= f.submit 'Sign up', class: 'btn btn-primary' %> +
+ <% end %> +
+ <%= render 'users/shared/links' %> +
+ +<% if @team and not @team.errors.empty? %> + +<% end %> diff --git a/app/views/users/shared/_links.html.erb b/app/views/users/shared/_links.html.erb index c98abe826..f0d9d4fea 100644 --- a/app/views/users/shared/_links.html.erb +++ b/app/views/users/shared/_links.html.erb @@ -1,5 +1,7 @@ <%- if controller_name != 'sessions' %> - <%= link_to t("devise.links.login"), new_session_path(resource_name) %>
+ <% login = t("devise.links.login") %> + <% login = t("devise.links.login_with_provider") if ['new_with_provider', 'create_with_provider'].include? action_name %> + <%= link_to login, new_session_path(resource_name) %>
<% end -%> <%- if devise_mapping.registerable? && Rails.configuration.x.enable_user_registration && controller_name != 'registrations' %> @@ -21,3 +23,14 @@ <%- if devise_mapping.omniauthable? && resource_class.omniauth_providers.any? %>
<% end -%> + +<%- if Rails.configuration.x.enable_user_registration && Rails.configuration.x.linkedin_signin_enabled %> + <%- if devise_mapping.omniauthable? && resource_class.omniauth_providers.any? && controller_name != 'registrations' %> + <%= link_to omniauth_authorize_path(resource_name, :linkedin), :title => "Sign in with LinkedIn" do %> + <%= image_tag 'linkedin/Sign-in-Small---Default.png', alt: "Sign in with LinkedIn", + onmouseover: "src='#{image_path('linkedin/Sign-in-Small---Hover.png')}'", + onmouseout: "src='#{image_path('linkedin/Sign-in-Small---Default.png')}'", + onclick: "src='#{image_path('linkedin/Sign-in-Small---Active.png')}'" %> + <% end -%> + <% end -%> +<% end -%> diff --git a/config/environments/development.rb b/config/environments/development.rb index 5f6bbe557..8ad2dc82a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -102,6 +102,9 @@ Rails.application.configure do config.x.enable_user_registration = ENV['ENABLE_USER_REGISTRATION'] == 'false' ? false : true + # Enable sign in with LinkedIn account + config.x.linkedin_signin_enabled = ENV['LINKEDIN_SIGNIN_ENABLED'] == 'true' + # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. #config.file_watcher = ActiveSupport::EventedFileUpdateChecker diff --git a/config/environments/production.rb b/config/environments/production.rb index 79504c7dc..21584572d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -116,6 +116,9 @@ Rails.application.configure do config.x.enable_user_registration = ENV['ENABLE_USER_REGISTRATION'] == 'false' ? false : true + # Enable sign in with LinkedIn account + config.x.linkedin_signin_enabled = ENV['LINKEDIN_SIGNIN_ENABLED'] == 'true' + # Use a different logger for distributed setups. # require 'syslog/logger' # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index af1646826..3929886a6 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -287,6 +287,8 @@ Devise.setup do |config| # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' + config.omniauth :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], + scope: %w(r_basicprofile r_emailaddress) # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or diff --git a/config/initializers/extends.rb b/config/initializers/extends.rb index 709c25017..37b9e1282 100644 --- a/config/initializers/extends.rb +++ b/config/initializers/extends.rb @@ -41,7 +41,8 @@ class Extends # Data type name should match corresponding model's name REPOSITORY_DATA_TYPES = { RepositoryTextValue: 0, - RepositoryDateValue: 1 } + RepositoryDateValue: 1, + RepositoryListValue: 2 } # List of implemented core API versions API_VERSIONS = ['20170715'] @@ -49,7 +50,7 @@ class Extends # Array used for injecting names of additional authentication methods for API API_PLUGABLE_AUTH_METHODS = [] - OMNIAUTH_PROVIDERS = [] + OMNIAUTH_PROVIDERS = [:linkedin, *(:developer if Rails.env.development?)] INITIAL_USER_OPTIONS = {} end diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index c88f1dccc..392784c53 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -11,6 +11,8 @@ Paperclip::Attachment.default_options.merge!( url: '/system/:class/:attachment/:id_partition/:hash/:style/:filename' ) +Paperclip::UriAdapter.register + if ENV['PAPERCLIP_STORAGE'] == "s3" if ENV['S3_BUCKET'].nil? or ENV['AWS_REGION'].nil? or diff --git a/config/locales/en.yml b/config/locales/en.yml index 6db4618fa..f508e4616 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -40,11 +40,17 @@ en: submit: "Resend unlock instructions" links: login: "Log in" + login_with_provider: "Log in with SciNote account" signup: "Sign up" forgot: "Forgot your password?" not_receive_confirmation: "Didn't receive confirmation instructions?" not_receive_unlock: "Didn't receive unlock instructions?" sign_in_provider: "Sign in with %{provider}" + linkedin: + provider_name: "LinkedIn" + complete_sign_up: "You have to complete the sign up process" + email_already_taken: "SciNote account with email %{email} alreday exists" + failed_to_save: "Failed to create new user" helpers: label: @@ -1272,6 +1278,8 @@ en: head_title: "Sign up" team_name_label: "Team name" team_name_help: "Team name is required in order to create your own Team. After you create your own Team, you will be able to join other Teams as well." + new_with_provider: + head_title: "Complete the Sign up" statistics: title: "My statistics" team: "Team" diff --git a/config/routes.rb b/config/routes.rb index 5679d1157..1e7afbb88 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -498,6 +498,8 @@ Rails.application.routes.draw do get 'avatar/:id/:style' => 'users/registrations#avatar', as: 'avatar' post 'avatar_signature' => 'users/registrations#signature' get 'users/auth_token_sign_in' => 'users/sessions#auth_token_create' + get 'users/sign_up_provider' => 'users/registrations#new_with_provider' + post 'users/complete_sign_up_provider' => 'users/registrations#create_with_provider' end namespace :api, defaults: { format: 'json' } do diff --git a/lib/tasks/data.rake b/lib/tasks/data.rake index 44be9f9b8..ab102ada9 100644 --- a/lib/tasks/data.rake +++ b/lib/tasks/data.rake @@ -69,6 +69,12 @@ namespace :data do .where.not(invitation_token: nil) .where("created_at < ?", Devise.invite_for.ago) destroy_users(users) + + # Remove users who didn't finish signup with LinkedIn + users = User.joins(:user_identities) + .where(confirmed_at: nil) + #.where('created_at < ?', Devise.confirm_within.ago) + destroy_users(users) end desc "Remove temporary and obsolete data"