From dd1c1e61f52ba95ad4e98125f2dd9bf0cbf1f412 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Wed, 13 Nov 2019 11:28:02 -0500 Subject: [PATCH] add captcha, controller, images --- .iex.exs | 3 +- assets/static/images/captcha/1.png | Bin 0 -> 1764 bytes assets/static/images/captcha/2.png | Bin 0 -> 2986 bytes assets/static/images/captcha/3.png | Bin 0 -> 3232 bytes assets/static/images/captcha/4.png | Bin 0 -> 2859 bytes assets/static/images/captcha/5.png | Bin 0 -> 3017 bytes assets/static/images/captcha/6.png | Bin 0 -> 3217 bytes assets/static/images/captcha/background.png | Bin 0 -> 1112 bytes assets/static/images/captcha/i1.png | Bin 0 -> 4971 bytes assets/static/images/captcha/i2.png | Bin 0 -> 7498 bytes assets/static/images/captcha/i3.png | Bin 0 -> 4536 bytes assets/static/images/captcha/i4.png | Bin 0 -> 5811 bytes assets/static/images/captcha/i5.png | Bin 0 -> 5938 bytes assets/static/images/captcha/i6.png | Bin 0 -> 5564 bytes lib/philomena/application.ex | 3 +- lib/philomena/captcha.ex | 130 ++++++++++++++++++ .../controllers/captcha_controller.ex | 11 ++ lib/philomena_web/router.ex | 1 + .../templates/captcha/create.html.slime | 20 +++ .../templates/pow/session/new.html.slime | 4 + lib/philomena_web/views/captcha_view.ex | 3 + mix.exs | 3 +- mix.lock | 1 + 23 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 assets/static/images/captcha/1.png create mode 100644 assets/static/images/captcha/2.png create mode 100644 assets/static/images/captcha/3.png create mode 100644 assets/static/images/captcha/4.png create mode 100644 assets/static/images/captcha/5.png create mode 100644 assets/static/images/captcha/6.png create mode 100644 assets/static/images/captcha/background.png create mode 100644 assets/static/images/captcha/i1.png create mode 100644 assets/static/images/captcha/i2.png create mode 100644 assets/static/images/captcha/i3.png create mode 100644 assets/static/images/captcha/i4.png create mode 100644 assets/static/images/captcha/i5.png create mode 100644 assets/static/images/captcha/i6.png create mode 100644 lib/philomena/captcha.ex create mode 100644 lib/philomena_web/controllers/captcha_controller.ex create mode 100644 lib/philomena_web/templates/captcha/create.html.slime create mode 100644 lib/philomena_web/views/captcha_view.ex diff --git a/.iex.exs b/.iex.exs index 2bbf4dd0..e8c7de4a 100644 --- a/.iex.exs +++ b/.iex.exs @@ -1,2 +1,3 @@ alias Philomena.{Repo, Comments.Comment, Posts.Post, Images.Image, Tags.Tag, Users.User} -import Ecto.Query \ No newline at end of file +import Ecto.Query +import Ecto.Changeset \ No newline at end of file diff --git a/assets/static/images/captcha/1.png b/assets/static/images/captcha/1.png new file mode 100644 index 0000000000000000000000000000000000000000..98493c224a6b599eeb0732d2667a895e250e7084 GIT binary patch literal 1764 zcmaJ?`8S&h8+~6PvBlC>#ZuZZj4G$ri4sbqQ?yK@2~BBZ8EFNHeXmT_S8a;Ulo=+9 z&{XXV5iuW$8jQW4EofCVleU(MrIyw*hdexBB2;%E8J3>%L#O{k5ggpHar4w z@+vbSY#0i2C+b7(A3rq1p1S8HG0lv}4u>Y294dc+Rk@5C3+)eJ(;wm6@THY%6-2w3 zF6O?$@e_tdcMUg_(SKMK5Je+Lhhwg{>nqHEC4qmr)SfhKRYZbd{uQ6fk6+eQV};qi z@~#so0U@S&eFvqr<%bKOD`mQzdE!`_`vp%%n;~cEe_mpZ?OYa&D^#5nx-ehXPLc)Ge#GW(#P(InqaOGES5AlqCOH)Sp&~RL6L>4OJ$1(x;3L+(gXQ8L zZGa@p0zsAq2_z;YAl?rbe;XhF4ImtPVxM1700NnR4t}Uy(yfAcmXAshL5?t?in1~> zEKGS(P`9?n^DT&y_yhWipu?N=iz_rK`U(`o+}Mx2}IhaWzCI^B&Aj z5H!!3SsLO8g?{FOy4)m6K){@_^@|y9w6VE=>)jN`S?hK`^W;lyk)rOXQ9#MpB7JoJ zQ=Ize5`5J$nMblfPb77BJF?IrafDZrgeBf@PZo7&Wl$^OK1&euBZ@QL-rfgtB{UXM zRTo7&Z0t#V)f^t4v+?sy_0L>U#(Bd{(CgyGU_Sv4s1NE<@oS-iQ(>D0*{Lf+PUqsHQTD`$d&N`1=B6`D z?i&yhRQ-R;-`}72m2grLmZ(jJ6fqcNoqEx!;?{}jzMf~aF3|Xpg3~x2gr&Vld9DK< zzB=`p)vMFJ!M|1TI2-{*C+NC-dF9Gg9cm4pY@ePE+GmeydgA69ZHYaRySHA2Lbo=| zNTCk{_>l(4+m$trtv_8f+7r44pG(NgAme0The9F!UIk4PCkrcIkiz+d#b%Bhf6dcF zz4xv+Zo3+eLZufUr3&p<8&mU5{!~pRrw3+0Hv+0_j2wYAsUm>5kJDnC8$%(DHG(xnqXn@y*s|4y1;(Eu%blxLtPiv9s$Fy|Z=ZNXgIcEUzNbf!6&= zitRN{lW`n)7Mhi{%o}x}=>sWqt;;%HfvZl#W$n+qZbM<>_0KVF*Y(E;oF{|GQuf4X r)@HQ`6;JPayGN}wME)B}ar2srMpGNpV>FKRLji8Co|sw};+?+%os>FQ literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/2.png b/assets/static/images/captcha/2.png new file mode 100644 index 0000000000000000000000000000000000000000..c6944f4d3f7756fa11b65729cd59abc4a36fac5d GIT binary patch literal 2986 zcma)8`8yPB7k&m=nk12Zsgb3!&samMkz}cc(8xM9p_j3*LnEIWp$*w7HG@R9$Ot2h zk|jnIGsrT?G9+7rzIp$G@B87Lb6w|$=enMA?)%(#;w3vv;k`0@0RX~Q=aDFGjrcbN z`MKHXx_&>m2nC$K8Vmq$(!T)-{Vd7hHl;%>oI~t!*pP6~pc^1OJY3Vq|5h-@GvJ0M zF6d^?l8FoePy;LEX@`j1MP{^(gOh^5GCNDUqL}wgBy(&ZubS_b5IwYgSzijmVI|Mc zH@lnmlSXdv^{Tu2R-ajWl`ciE(PO@zBa0{|mIP+#57HKgz00mnqJRE@Iah|YL;|!p zzqk}@cU|P2eF#>ar!`<@!%C$-oW+38EKlY}v+FnVA^$mWM)1i0O4#QUt^_H2Bw`PB z5(K58WZ*@-#RAJpaQ8}dnI*%2BNE6BJ)wPk1`R-?(LpFwzX^b5)k~Q>8t9ioDq6AC zjV`XPF-o<{3-09o74$iq{!k_E9Q_4D;*`h@w!a@eR&pclU?) z@9$+$LQ8M;p9AxaZfwgP$3!W(Eg{icop3WVvI*4*Ieduv#d}WGCX-ND2uR-VPz$RvbTSn zp1!Auo|v4R>~`Do@B!-2ucd*T%bt^ESFr4ITe0yH`y!Q1d=nJVreC%C~oTpDE)SWAUq?Q{W;g5&5VR>zB zZF%pBqaQ^3;K(*)n}CSIly`P^_U2b7_vzeRIsN|d7$dp;v0Kv__4V~e6YDo_+*k-P zPN`wHH;gt0vQ@OHn>)LE8<&1fhU^!N7@UDx_a)+yT$)|__!WGj#EdFL*X zMEdHypO5GHM%_Q(??5Fr0m$64DCpg&i=IAiXh{5;@B#m|SVt`0Sa-`8FhP z?i|nS`KVcuyho1!P}9=tD0giD;6ll5?q0%UH4AXfJNjT;lhPXRaJHO7-LBM66GpYeQ?7hTfzZ^QXFnXx|{jw~RM{ zU3&d+S66RT<7g?9X{M@rQykvR2dZ!O(iXl~xAy0nMCuM$z*onj-F*X_9m2xaHybQp zQR0caR><6(oX;7WuJ;W;R(iGX#XNd3Iv1kSUdRLEN7!=S>fCwjH&RP%F^yjT$2${6 zuhCf1te#bYT~IAFhD}_p#s*qjTRR8Dw;a~G_U?;!qd|3bb@c7$Mh|T2MV5|{21bBx z8tPlEpUbx^N5Qu`oT6QUncwT(5;B>EzWwy_??+#r!T|VPVnuk?Eh0?U3->W;1c@xY{OvAe@sK;&X|X;H*hEo&)bWY-9rMFf3k!>L^L|Q&%Ptme z)R#WPv6H!VRaLqZP2n96onLdoPv~+7?@m=D(moJY__*`~zk?qaYX^jZ_!4VQu zIZA6_RO-&61H8N@qC(7mH%6|qPA-+|;?uCh$Fs~7|yzM(qFFVWGp=< zb@ue+pGE%Vsh~yBy(%+xspO`a;_8uYQ_z)TATmiyNy=Pe)CbdE9tRckOTF~|{wHE$ zVv2Rn>dHWZmxvIsA2^oFuWK(LMNI;CPmn5Ncm5P7uCvF+LPG^a{mymZ)4?MMHL)QI zp7A+B@7Cb>)Th+Vsnm0J1p@$=Kzjy?4x zHMNyRb-3`OGyMe3rlv;+Lwi5Hy7k+v#34D0rDlBckju4!u0g? z5P1i`=wx|gFiJ8qG66e(LO1bd17E*B=c@Z}U%!-CGN$^wcG!ZmxTGZJd({moJzsG! zo~W8n%{Pq(9!NjGMR8D6h}9)zPN*4cY2lDAE+dygDrYrXLjua`EqG{~qkn`;XvAeG z{1kh2%SOklu7a}0@Tm! z@_7T^IPwQ5oO2XxZW6VSl&gSms#Hdpe!IC?q6wD;=c;so<5@Ko5ngk@iQL zDA>!{<``3V;)vJ4df{YIBmiCSM`l*bi0&nn-jE`zo$mQH$09Ph$D%{|oIF(+yK9ZN rR`!CKnlkeDx&g4VutS!g@woF}xJ#+- literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/3.png b/assets/static/images/captcha/3.png new file mode 100644 index 0000000000000000000000000000000000000000..add098016207332fb8369f7975d048ce727e827f GIT binary patch literal 3232 zcma)9_d6Tv7msm?tteGgqt!}nLalPE+$O0=8>>c)x@jmyt)w>98MA^KNm^~xsI7b} zW~~ydMzlsy>rz|n_09bc?(>}Up67Xgc;EA$^Esc-^S-=oc~gl0EI$AM5Q0I?Q0$2R z*MU6jRsV0@es<~4m7_TXyto95a;HP0pM^rHBTR}0CzV( zjGC`MHfzP`EC3*=3NyQIjn7^l3-^=2kQ>)m2gEndy#QUxz#909O5$2?NP%MUb8*#g zOYhD-SZyg9k?OOuEa9h18TsrK_Ymnt@H;+3*M(2+4%*OFw?#{55>?Fa zZ4u9N-+v9#q#1NAUDO`vJxUJrHNE5`_FCG|h*Ds^Wpu&g7vp5frCb6a30 z-fAm=YE5%HbCZZ_0CIDN=M%I(kG+|Ud-duSXB6JZnLkW?SMmld)yhMia|wP?te5*q z(;DmP-q2(w_bo7mr(Ps%n!Y$YH-~a@>3vu|-u7DYmXfma1rrmBpPq%D>?Kj4-&~jU z$mpo2m)C`JiKEYh`9X~RqvJ&Ez7whg!N(MVpzYOSC!fjqynXjB`q?v{2VPzsot>Gt zvmzQOa)!aBz7xho6d;|5@}kjbNTe@oVLFpLw2t}E^u@9%&^c_~+&>^d6OppG_<*0E zzqnwTi&uEj9(01?lOTZ*{^9U8Rz!V& z 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 literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/5.png b/assets/static/images/captcha/5.png new file mode 100644 index 0000000000000000000000000000000000000000..20fcbe851fdbb2dd9a05110960965f1bdff1281c GIT binary patch literal 3017 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 S&auaEz)d3ySdF1;(*FSOW!{zm literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/6.png b/assets/static/images/captcha/6.png new file mode 100644 index 0000000000000000000000000000000000000000..6c96307da067f547c0fa5ef42b93ce4a2183a050 GIT binary patch literal 3217 zcmb7{`#%%x8^_0T$YG}V5;>KJW=@Z!m_v^+CaOtN&YD@yXEED^C-P)rO5~WyR1R~< zq1i-)@YE_f4=pj9vz&d`fAIZYulu^M*X#c2y06#udEeKacG(dwDW)I>001QIY^{*| z82j5rh55VjEu&BTa5&V~H39$trvG++6wDA%2lD-r*=fOiYX}CO9C% z*EIYLoIVSIa zUXE&AJAke{Qg}JC5+S+_^fJ+R77eq9L^(j%{k^^0Z(hCXx0vWQzNX_sc3xSn;H36`tLT~wan2E_gI*_WHK+Dk}0jO)*Fwe3+)ec){P!4drwMdNY#+S57&rS)U1vLpS6FaT~b+jzqc2m z1%*Piv=GBXi@zea*D!hc`Ix}KPR{y>wb-}JqM`$$CwBSWE7(VnjwFOlB$E=5h(E|z z6^#Nf7vZ)kRBd}n7xg1ob~d<9zs6&VsGMx%{=m$#wl3dZQYbyg7dJAJedB8|d3fDq ze?f!imx>0U)odDOahl}friwS1&8=-?{zp$K*Oxt9q=Z;~^)7E#}Rn5%In#O~bV_5?C)6Wf{Eu_rrRJ+nA!;`X`&-3yWU`+=i^1eeYwNv## zoV+Rwme1~ctSK8f**5Ozai~zu==z`PAN?a0!B-GrKmRR>#o617hZ8iSZ=mpARryUzjwA6zg=fAkNXN!yITfj$u83K+ARtL2(7g%jD+d$PUt@ zxeELq-Y`-+Nol3i>4$B{UfYW<$Cwu_R)?{2B2IL#d67SBs~sYf$#z@r?(WO=U>_@| zkh|@y^<$^~uJUtyRjhQBk;D_%r$RRc+V&)J1e$V?!Cr;nY4npPPact0 ziow&K8q7Km_#yfC4M&ZQjqQYFWo2)n(agz7B642Gryb}+iywGutbM(PaR0s-U++Bw z1Lf7#L@)i+$;H`kwZ2bHqQv^B5?(pT+iV820x!?Y-LU$e3TSoH<$QhhZNa&ZD*X70 zt7}i%QB5z^rgS;IA0Oc=?2>!R3S%A2mTIqL?fUKu`^f8z@) zG~gaHZtd=_#AdSt$6I7sg|_Nc#n@Y<{K)QeCm7Am%~y70l+vt_y(;kwwPk~Qdwa*t z;z(UxHXs%Ar-maasFs$`mrCcrv8F#!k%7!|hfS=x2YxS#ppswS{1&oWtYnWkmW8Zr zX=zz>D_EL;QC-Qm&NdLCB#@C}36I>Mtd{wY(={8t z-KR&t2q`j&(u$ZJ5IPSzGZs}=K%i}$8YqMaswV$ir`3&w!@Gri#Je{)XNb(;RaO!o zWONeJ@fa^gLV2_4&T4+H&56v<>@*N77XW+&E|vCKEzUuh`Bq(*_LMV9NpuEZC?WL< zBW>D`#77z`IPfMwQ)K|(YTcg;3*W!@WJB2L|Ix8TVDP&yysw%awRM%iv3ql3TPiAS zMPgr~{QPi$H336I!!nZM-|Z)fo%bFDh>MFe^(IxUM6ZA@BavC8qJNXBjn`4y8DdNC z(&efFI|37TW((R^YYE?)))*leziZdN2F)6_j`Lg@Zks>_insJbXfco z4dcml3*~-8B;kSQB7R&P@mPp%y|dbXmMg9cj2+ScN3V>;EyozyLx`@A*gzbpCUnZu zBX%mK%)|r+oBNrn7k%!G->YN3juQIin0-wk=V4>eXjenP5VDa{Sy@V+9~amY8K6c!dP%8osQ6Dz4y16ULN zU5SNnw#{FE{Z(jojDeeU_Vt~q0V+PQ`Jx!|CR2Wl#W15jGu}9R?j!BjM82$qF#eC^ z&6}`lDm5#L^R^Owf6IchPcV!iYy+0d`A;xq zF)^`RSd8vzzYks`^%$!Y(v~G)IbAo_SaU>@CV1CIbUC7W2=?i<(8W{PS`2XfEBfGU zy!@u3TIU6IZB+Av10j#~E$l(c1r^@&({qAPE8e`p-oWDzEc>Xuqn5i5za30IgfH|P zyQF||YF6pq@^n5BFBNE%{vQMO?@`=H{Xptx5AVu)59Jj9I{~n>cC@Op^t$_B<)%d> literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/background.png b/assets/static/images/captcha/background.png new file mode 100644 index 0000000000000000000000000000000000000000..af1e9b26c1b841206b39fb0ff78e46483a59b261 GIT binary patch literal 1112 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wqv4kn<;*YU85o%Nc)B=-RNQ)dePb?*fdKPC`|vYC5u1$N`JEM;XL9lJ zh+V4vrV?qra_!VLDNF6` zeORWFt-f{Zq^WD39A*5m3SkXl{m8~1BH6767JF|h3%`80pUb*H4^tm|ugVjuMYmgKoQUT6*B_px*>z%yi nn|s|4802V)Z3eDv_T!!SChHhZ>r?8xK^ffB)z4*}Q$iB}sx>23 literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/i1.png b/assets/static/images/captcha/i1.png new file mode 100644 index 0000000000000000000000000000000000000000..44c64070ffeac237e241536311a9963ac96874e8 GIT binary patch literal 4971 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 literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/i2.png b/assets/static/images/captcha/i2.png new file mode 100644 index 0000000000000000000000000000000000000000..03fe0d25b00fe044c16da6ab93522869beb41d80 GIT binary patch literal 7498 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 literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/i3.png b/assets/static/images/captcha/i3.png new file mode 100644 index 0000000000000000000000000000000000000000..43b1acc0da1444bb73802a73d602e584ee444d21 GIT binary patch literal 4536 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 U=cD;=AOHXW07*qoM6N<$g1;ehxBvhE literal 0 HcmV?d00001 diff --git a/assets/static/images/captcha/i6.png b/assets/static/images/captcha/i6.png new file mode 100644 index 0000000000000000000000000000000000000000..09f8e3a37e61454b2bd35958ade47d50e30cd378 GIT binary patch literal 5564 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 KMNUMnLSTZWq1uW7 literal 0 HcmV?d00001 diff --git a/lib/philomena/application.ex b/lib/philomena/application.ex index a78bf76a..e7e3c37c 100644 --- a/lib/philomena/application.ex +++ b/lib/philomena/application.ex @@ -14,7 +14,8 @@ defmodule Philomena.Application do PhilomenaWeb.Endpoint, # Starts a worker by calling: Philomena.Worker.start_link(arg) # {Philomena.Worker, arg}, - Pow.Store.Backend.MnesiaCache + Pow.Store.Backend.MnesiaCache, + {Redix, name: :redix} ] # See https://hexdocs.pm/elixir/Supervisor.html diff --git a/lib/philomena/captcha.ex b/lib/philomena/captcha.ex new file mode 100644 index 00000000..820bb10d --- /dev/null +++ b/lib/philomena/captcha.ex @@ -0,0 +1,130 @@ +defmodule Philomena.Captcha do + defstruct [:image_base64, :solution, :solution_id] + + @numbers ~W(1 2 3 4 5 6) + @images ~W(1 2 3 4 5 6) + @base_path File.cwd!() <> "/assets/static/images/captcha" + + @number_files %{ + "1" => @base_path <> "/1.png", + "2" => @base_path <> "/2.png", + "3" => @base_path <> "/3.png", + "4" => @base_path <> "/4.png", + "5" => @base_path <> "/5.png", + "6" => @base_path <> "/6.png" + } + + @image_files %{ + "1" => @base_path <> "/i1.png", + "2" => @base_path <> "/i2.png", + "3" => @base_path <> "/i3.png", + "4" => @base_path <> "/i4.png", + "5" => @base_path <> "/i5.png", + "6" => @base_path <> "/i6.png" + } + + @background_file @base_path <> "/background.png" + + @geometry %{ + 1 => "+0+0", 2 => "+120+0", 3 => "+240+0", + 4 => "+0+120", 5 => "+120+120", 6 => "+240+120", + 7 => "+0+240", 8 => "+120+240", 9 => "+240+240" + } + + @distortion_1 [ + ~W"-implode .1", + ~W"-implode -.1" + ] + + @distortion_2 [ + ~W"-swirl 10", + ~W"-swirl -10", + ~W"-swirl 20", + ~W"-swirl -20" + ] + + @distortion_3 [ + ~W"-wave 5x180", + ~W"-wave 5x126", + ~W"-wave 10x180", + ~W"-wave 10x126" + ] + + def create do + solution = + Enum.zip(@numbers, Enum.shuffle(@images)) + |> Map.new() + + # 3x3 render grid + grid = Enum.shuffle(@numbers ++ [nil, nil, nil]) + + # Base arguments + args = [ + "-page", "360x360", + @background_file + ] + + # Individual grid files + files = + grid + |> Enum.with_index() + |> Enum.flat_map(fn {num, index} -> + if num do + [ + "(", @image_files[solution[num]], ")", "-geometry", @geometry[index + 1], "-composite", + "(", @number_files[num], ")", "-geometry", @geometry[index + 1], "-composite" + ] + else + [] + end + end) + + # Distortions for more unpredictability + distortions = + [ + Enum.random(@distortion_1), + Enum.random(@distortion_2), + Enum.random(@distortion_3) + ] + |> Enum.shuffle() + |> List.flatten() + + jpeg = ~W"-quality 8 jpeg:-" + + {image, 0} = System.cmd("convert", args ++ files ++ distortions ++ jpeg) + image = image |> Base.encode64() + + # Store solution in redis to prevent reuse + # Solutions are valid for 10 minutes + solution_id = + :crypto.strong_rand_bytes(12) + |> Base.encode16(case: :lower) + solution_id = "cp_" <> solution_id + + {:ok, _ok} = Redix.command(:redix, ["SET", solution_id, Jason.encode!(solution)]) + {:ok, _ok} = Redix.command(:redix, ["EXPIRE", solution_id, 600]) + + %Philomena.Captcha{ + image_base64: image, + solution: solution, + solution_id: solution_id + } + end + + def valid_solution?(<<"cp_", _rest::binary>> = solution_id, solution) do + # Delete key immediately. This may race, but should + # have minimal impact if the race succeeds. + with {:ok, sol} <- Redix.command(:redix, ["GET", solution_id]), + {:ok, _del} <- Redix.command(:redix, ["DEL", solution_id]), + {:ok, sol} <- Jason.decode(to_string(sol)) + do + Map.equal?(solution, sol) + else + _ -> + false + end + end + + def valid_solution?(_solution_id, _solution), + do: false +end diff --git a/lib/philomena_web/controllers/captcha_controller.ex b/lib/philomena_web/controllers/captcha_controller.ex new file mode 100644 index 00000000..705936db --- /dev/null +++ b/lib/philomena_web/controllers/captcha_controller.ex @@ -0,0 +1,11 @@ +defmodule PhilomenaWeb.CaptchaController do + use PhilomenaWeb, :controller + + alias Philomena.Captcha + + def create(conn, _params) do + captcha = Captcha.create() + + render(conn, "create.html", captcha: captcha, layout: false) + end +end \ No newline at end of file diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index edf178e9..08a79109 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -67,6 +67,7 @@ defmodule PhilomenaWeb.Router do end resources "/filters", FilterController resources "/profiles", ProfileController, only: [:show] + resources "/captchas", CaptchaController, only: [:create] get "/:id", ImageController, :show end diff --git a/lib/philomena_web/templates/captcha/create.html.slime b/lib/philomena_web/templates/captcha/create.html.slime new file mode 100644 index 00000000..650cc52b --- /dev/null +++ b/lib/philomena_web/templates/captcha/create.html.slime @@ -0,0 +1,20 @@ +elixir: + options = [ + "Applejack": 1, + "Fluttershy": 2, + "Pinkie Pie": 3, + "Rainbow Dash": 4, + "Rarity": 5, + "Twilight Sparkle": 6 + ] + +div + = hidden_input :captcha, :id, value: @captcha.solution_id + img src="data:image/jpeg;base64,#{@captcha.image_base64}" + + = for i <- (1..6) do + .field + label> for="captcha_sln[#{i}]" + | Name of pony with cutie mark # + = i + = select :captcha, "sln[#{i}]", options, class: "input" diff --git a/lib/philomena_web/templates/pow/session/new.html.slime b/lib/philomena_web/templates/pow/session/new.html.slime index 24b51147..4b65a30d 100644 --- a/lib/philomena_web/templates/pow/session/new.html.slime +++ b/lib/philomena_web/templates/pow/session/new.html.slime @@ -19,6 +19,10 @@ h1 Sign in = checkbox f, :persistent_session = label f, :persistent_session, "Remember me" + .field + = checkbox f, :captcha, class: "js-captcha", value: 0 + = label f, :captcha, "I am not a robot!" + = submit "Sign in", class: "button" p diff --git a/lib/philomena_web/views/captcha_view.ex b/lib/philomena_web/views/captcha_view.ex new file mode 100644 index 00000000..12dc3e7e --- /dev/null +++ b/lib/philomena_web/views/captcha_view.ex @@ -0,0 +1,3 @@ +defmodule PhilomenaWeb.CaptchaView do + use PhilomenaWeb, :view +end diff --git a/mix.exs b/mix.exs index 8db1d8c8..32c72351 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,8 @@ defmodule Philomena.MixProject do {:canary, "~> 1.1.1"}, {:scrivener_ecto, "~> 2.0"}, {:pbkdf2, "~> 2.0"}, - {:qrcode, "~> 0.1.5"} + {:qrcode, "~> 0.1.5"}, + {:redix, "~> 0.10.2"} ] end diff --git a/mix.lock b/mix.lock index cefdf126..59dac626 100644 --- a/mix.lock +++ b/mix.lock @@ -43,6 +43,7 @@ "pow": {:hex, :pow, "1.0.13", "5ca3e8d9fecca037bfb0ea3b8dde070cc319746498e844d59fc209d461b0d426", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3.0 or ~> 1.4.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 2.0.0 and <= 3.0.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, ">= 1.5.0 and < 2.0.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"}, "qrcode": {:hex, :qrcode, "0.1.5", "551271830515c150f34568345b060c625deb0e6691db2a01b0a6de3aafc93886", [:mix], [], "hexpm"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"}, + "redix": {:hex, :redix, "0.10.2", "a9eabf47898aa878650df36194aeb63966d74f5bd69d9caa37babb32dbb93c5d", [:mix], [{:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"}, "retry": {:hex, :retry, "0.13.0", "bb9b2713f70f39337837852337ad280c77662574f4fb852a8386c269f3d734c4", [:mix], [], "hexpm"}, "scrivener": {:hex, :scrivener, "2.7.0", "fa94cdea21fad0649921d8066b1833d18d296217bfdf4a5389a2f45ee857b773", [:mix], [], "hexpm"}, "scrivener_ecto": {:hex, :scrivener_ecto, "2.2.0", "53d5f1ba28f35f17891cf526ee102f8f225b7024d1cdaf8984875467158c9c5e", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm"},